summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changes5
-rw-r--r--aa2
-rwxr-xr-xb.rb2
-rwxr-xr-xdocs/b.rb3
-rw-r--r--extconf.rb2
-rw-r--r--mmap.c192
-rw-r--r--mmap.html210
-rw-r--r--mmap.rd75
-rw-r--r--tests/mmapt.rb4
9 files changed, 354 insertions, 141 deletions
diff --git a/Changes b/Changes
index 683bacc..aac511c 100644
--- a/Changes
+++ b/Changes
@@ -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)
diff --git a/aa b/aa
deleted file mode 100644
index 9f9c530..0000000
--- a/aa
+++ /dev/null
@@ -1,2 +0,0 @@
-123
-abc
diff --git a/b.rb b/b.rb
index 2acbcf2..617cd8b 100755
--- a/b.rb
+++ b/b.rb
@@ -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
diff --git a/docs/b.rb b/docs/b.rb
index 2b7adfb..0839bb3 100755
--- a/docs/b.rb
+++ b/docs/b.rb
@@ -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
diff --git a/extconf.rb b/extconf.rb
index 07c59ad..1e8f37f 100644
--- a/extconf.rb
+++ b/extconf.rb
@@ -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
diff --git a/mmap.c b/mmap.c
index 83df09a..df6dade 100644
--- a/mmap.c
+++ b/mmap.c
@@ -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()
{
diff --git a/mmap.html b/mmap.html
index 3eaf01a..0cf909e 100644
--- a/mmap.html
+++ b/mmap.html
@@ -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> &gt; <var>other</var></code></a><!-- RDLabel: "self > other" -->
-<dt><a name="label:31" id="label:31"><code><var>self</var> &gt;= <var>other</var></code></a><!-- RDLabel: "self >= other" -->
-<dt><a name="label:32" id="label:32"><code><var>self</var> &lt; <var>other</var></code></a><!-- RDLabel: "self < other" -->
-<dt><a name="label:33" id="label:33"><code><var>self</var> &lt;= <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> &lt;&lt; <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> &lt;=&gt; <var>other</var></code></a><!-- RDLabel: "self <=> other" -->
-<dt><a name="label:44" id="label:44"><code>&lt;&lt;(<var>other</var>)</code></a><!-- RDLabel: "<<" -->
-<dt><a name="label:45" id="label:45"><code>casecmp(<var>other</var>) &gt;= <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>) &gt;= <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> &gt; <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> &gt;= <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> &lt; <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> &lt;= <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> &lt;&lt; <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> &lt;=&gt; <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>) &gt;= <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>) &gt;= <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>
diff --git a/mmap.rd b/mmap.rd
index 81fd8d8..7cf978e 100644
--- a/mmap.rd
+++ b/mmap.rd
@@ -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!>")