diff options
-rw-r--r-- | Changes | 7 | ||||
-rw-r--r-- | README.en | 3 | ||||
-rwxr-xr-x | docs/b.rb | 108 | ||||
-rw-r--r-- | docs/mmap.rb | 320 | ||||
-rw-r--r-- | extconf.rb | 22 | ||||
-rw-r--r-- | mmap.c | 116 | ||||
-rw-r--r-- | mmap.html | 529 | ||||
-rw-r--r-- | mmap.rd | 126 | ||||
-rw-r--r-- | tests/mmapt.rb | 15 | ||||
-rw-r--r-- | tests/runit_.rb | 44 |
10 files changed, 835 insertions, 455 deletions
@@ -37,3 +37,10 @@ * added "a" for ::new * experimental EXP_INCR_SIZE (4096) ("increment" => 4096) * tests for RUNIT/Test::Unit + +-- 0.1.8 + +* test for madvise(2) +* don't test size for MAP_ANON +* added syntax Mmap(nil, length) +* documentation : make rd2; make rdoc @@ -9,6 +9,9 @@ * Documentation + make rd2 + make rdoc + See mmap.rd, mmap.html * Tests : if you have rubyunit diff --git a/docs/b.rb b/docs/b.rb new file mode 100755 index 0000000..2b7adfb --- /dev/null +++ b/docs/b.rb @@ -0,0 +1,108 @@ +#!/usr/bin/ruby + +def yield_or_not(primary) + text = primary.sub(/\{\s*\|([^|]+)\|[^}]*\}/, '') + if text != primary + "def #{text}yield #$1\nend" + else + "def #{text}end" + end +end + +def normalize(text) + norm = text.gsub(/\(\(\|([^|]+)\|\)\)/, '<em>\\1</em>') + norm.gsub(/\(\(\{/, '<tt>').gsub!(/\}\)\)/, '</tt>') + norm.gsub!(/\(\(<([^|>]+)[^>]*>\)\)/, '<em>\\1</em>') + norm.gsub!(/^\s*:\s/, ' * ') + norm +end + +def intern_def(text, names, fout) + fout.puts "##{normalize(text.join('#'))}" + fout.puts yield_or_not(names[0]) + if names.size > 1 + n = names[0].chomp.sub(/\(.*/, '') + names[1 .. -1].each do |na| + nd = na.chomp.sub(/\(.*/, '') + if nd != n + fout.puts "#same than <em>#{n}</em>" + fout.puts yield_or_not(na) + end + end + end +end + +def output_def(text, names, keywords, fout) + if ! names.empty? + keywords.each do |k| + fout.puts k + intern_def(text, names, fout) + fout.puts "end" if k != "" + end + end +end + +def loop_file(file, fout) + text, keywords, names = [], [""], [] + comment = false + rep, indent, vide = '', -1, nil + IO.foreach(file) do |line| + if /^#\^/ =~ line + comment = ! comment + next + end + if comment + fout.puts "# #{normalize(line)}" + next + end + case line + when /^\s*$/ + vide = true + text.push line + when /^#\^/ + comment = ! comment + when /^##/ + line[0] = ?\s + fout.puts line + when /^#\s*(.+?)\s*$/ + keyword = $1 + output_def(text, names, keywords, fout) + text, names = [], [] + keywords = keyword.split(/\s*##\s*/) + if keywords.size == 1 + fout.puts keywords[0] + keywords = [""] + end + when /^#/ + when /^---/ + name = $' + if vide + output_def(text, names, keywords, fout) + text, names = [], [] + rep, indent, vide = '', -1, false + end + names.push name + else + vide = false + if line.sub!(/^(\s*): /, '* ') + indent += ($1 <=> rep) + rep = $1 + else + line.sub!(/^#{rep}/, '') + end + if indent >= 0 + line = (' ' * indent) + line + else + line.sub!(/\A\s*/, '') + end + text.push line + end + end +end + +File.open("#{ARGV[0]}.rb", "w") do |fout| + loop_file("../#{ARGV[0]}.rd", fout) + Dir['*.rd'].each do |file| + loop_file(file, fout) + end +end diff --git a/docs/mmap.rb b/docs/mmap.rb new file mode 100644 index 0000000..ba00571 --- /dev/null +++ b/docs/mmap.rb @@ -0,0 +1,320 @@ +# The Mmap class implement memory-mapped file objects +# +# === WARNING +# === The variables $' and $` are not available with gsub! and sub! +class Mmap +include Comparable +include Enumerable +class << self + +#disable paging of all pages mapped. <em>flag</em> can be +#<em>Mmap::MCL_CURRENT</em> or <em>Mmap::MCL_FUTURE</em> +# +def lockall(flag) +end + +#create a new Mmap object +# +#* <em>file</em> +# Pathname of the file, if <em>nil</em> is given an anonymous map +# is created <em>Mmanp::MAP_ANON</em> +# +#* <em>mode</em> +# Mode to open the file, it can be "r", "w", "rw", "a" +# +#* <em>protection</em> +# specify the nature of the mapping +# +# * <em>Mmap::MAP_SHARED</em> +# Creates a mapping that's shared with all other processes +# mapping the same areas of the file. +# The default value is <em>Mmap::MAP_SHARED</em> +# +# * <em>Mmap::MAP_PRIVATE</em> +# Creates a private copy-on-write mapping, so changes to the +# contents of the mmap object will be private to this process +# +#* <em>options</em> +# Hash. If one of the options <em>length</em> or <em>offset</em> +# is specified it will not possible to modify the size of +# the mapped file. +# +# * <em>length</em> +# Maps <em>length</em> bytes from the file +# +# * <em>offset</em> +# The mapping begin at <em>offset</em> +# +# * <em>advice</em> +# The type of the access (see #madvise) +# +# +def new(file, mode = "r", protection = Mmap::MAP_SHARED, options = {}) +end + +#reenable paging +# +def unlockall +end +end + +#add <em>count</em> bytes to the file (i.e. pre-extend the file) +# +def extend(count) +end + +#<em>advice</em> can have the value <em>Mmap::MADV_NORMAL</em>, +#<em>Mmap::MADV_RANDOM</em>, <em>Mmap::MADV_SEQUENTIAL</em>, +#<em>Mmap::MADV_WILLNEED</em>, <em>Mmap::MADV_DONTNEED</em> +# +def madvise(advice) +end + +#change the mode, value must be "r", "w" or "rw" +# +def mprotect(mode) +end + +#disable paging +# +def mlock +end + +#flush the file +# +def msync +end +#same than <em> msync</em> +def flush +end + +#reenable paging +# +def munlock +end + +#terminate the association +# +#=== Other methods with the same syntax than for the class String +# +# +def munmap +end + +# +def self == other +end + +# +def self > other +end + +# +def self >= other +end + +# +def self < other +end + +# +def self <= other +end + +# +def self === other +end + +# +def self << other +end + +# +def self =~ other +end + +# +def self[nth] +end + +# +def self[start..last] +end + +# +def self[start, length] +end + +# +def self[nth] = val +end + +# +def self[start..last] = val +end + +# +def self[start, len] = val +end + +# +def self <=> other +end + +# +def <<(other) +end + +# +def casecmp(other) >= 1.7.1 +end + +# +def concat(other) +end + +# +def capitalize! +end + +# +def chop! +end + +# +def chomp!([rs]) +end + +# +def count(o1 [, o2, ...]) +end + +# +def crypt(salt) +end + +# +def delete!(str) +end + +# +def downcase! +end + +# +def each_byte +yield char +end + +# +def each([rs]) +yield line +end + +# +def each_line([rs]) +yield line +end + +# +def empty? +end + +# +def freeze +end + +# +def frozen +end + +# +def gsub!(pattern, replace) +end + +# +def gsub!(pattern) +yield str +end + +# +def include?(other) +end + +# +def index(substr[, pos]) +end + +# +def insert(index, str) >= 1.7.1 +end + +# +def length +end + +# +def reverse! +end + +# +def rindex(substr[, pos]) +end + +# +def scan(pattern) +end + +# +def scan(pattern) +yield str +end + +# +def size +end + +# +def slice +end + +# +def slice! +end + +# +def split([sep[, limit]]) +end + +# +def squeeze!([str]) +end + +# +def strip! +end + +# +def sub!(pattern, replace) +end + +# +def sub!(pattern) +yield str +end + +# +def sum([bits]) +end + +# +def swapcase! +end + +# +def tr!(search, replace) +end + +# +def tr_s!(search, replace) +end @@ -14,7 +14,29 @@ unknown: $(DLLIB) \t@echo "main() {}" > /tmp/a.c \t$(CC) -static /tmp/a.c $(OBJS) $(CPPFLAGS) $(DLDFLAGS) -lruby #{CONFIG["LIBS"]} $(LIBS) $(LOCAL_LIBS) \t@-rm /tmp/a.c a.out + +%.html: %.rd +\trd2 $< > ${<:%.rd=%.html} + EOT + make.print "HTML = mmap.html" + docs = Dir['docs/*.rd'] + docs.each {|x| make.print " \\\n\t#{x.sub(/\.rd$/, '.html')}" } + make.print "\n\nRDOC = mmap.rd" + docs.each {|x| make.print " \\\n\t#{x}" } + make.puts + make.print <<-EOF + +rdoc: docs/doc/index.html + +docs/doc/index.html: $(RDOC) +\t@-(cd docs; b.rb mmap; rdoc mmap.rb) + +rd2: html + +html: $(HTML) + + EOF ensure make.close end @@ -8,6 +8,17 @@ #include <intern.h> #include "version.h" +#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] @@ -40,8 +51,7 @@ typedef struct { MMAP_RETTYPE addr; int smode, pmode, vscope; int advice, frozen, lock; - size_t len, real; - size_t size, incr; + size_t len, real, incr; off_t offset; char *path; } mm_mmap; @@ -201,9 +211,11 @@ mm_expandf(t_mm, len) 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->lock && mlock(t_mm->addr, len) == -1) { rb_raise(rb_eArgError, "mlock(%d)", errno); } @@ -253,9 +265,9 @@ mm_i_options(arg, obj) key = rb_obj_as_string(key); options = RSTRING(key)->ptr; if (strcmp(options, "length") == 0) { - t_mm->size = NUM2INT(value); - if (t_mm->size <= 0) { - rb_raise(rb_eArgError, "Invalid value for length %d", t_mm->size); + t_mm->len = NUM2INT(value); + if (t_mm->len <= 0) { + rb_raise(rb_eArgError, "Invalid value for length %d", t_mm->len); } t_mm->frozen |= MM_FIXED; } @@ -309,7 +321,7 @@ mm_s_new(argc, argv, obj) VALUE res, fname, vmode, scope, options; mm_mmap *t_mm; char *path, *mode; - size_t size; + size_t size = 0; off_t offset; options = Qnil; @@ -321,7 +333,7 @@ mm_s_new(argc, argv, obj) vscope = 0; #ifdef MAP_ANON if (NIL_P(fname)) { - vscope = MAP_ANON; + vscope = MAP_ANON | MAP_SHARED; path = 0; } else { @@ -338,40 +350,40 @@ mm_s_new(argc, argv, obj) Check_SafeStr(fname); path = RSTRING(fname)->ptr; #endif - perm = 0666; - if (NIL_P(vmode)) { - mode = "r"; - } - else if (TYPE(vmode) == T_ARRAY && RARRAY(vmode)->len >= 2) { - VALUE tmp = RARRAY(vmode)->ptr[0]; - mode = STR2CSTR(tmp); - perm = NUM2INT(RARRAY(vmode)->ptr[1]); - } - else { - mode = STR2CSTR(vmode); - } - if (strcmp(mode, "r") == 0) { - smode = O_RDONLY; - pmode = PROT_READ; - } - else if (strcmp(mode, "w") == 0) { - smode = O_WRONLY; - pmode = PROT_WRITE; - } - 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); - } vscope |= NIL_P(scope) ? MAP_SHARED : NUM2INT(scope); size = 0; + perm = 0666; if (path) { + if (NIL_P(vmode)) { + mode = "r"; + } + else if (TYPE(vmode) == T_ARRAY && RARRAY(vmode)->len >= 2) { + VALUE tmp = RARRAY(vmode)->ptr[0]; + mode = STR2CSTR(tmp); + perm = NUM2INT(RARRAY(vmode)->ptr[1]); + } + else { + mode = STR2CSTR(vmode); + } + if (strcmp(mode, "r") == 0) { + smode = O_RDONLY; + pmode = PROT_READ; + } + else if (strcmp(mode, "w") == 0) { + smode = O_WRONLY; + pmode = PROT_WRITE; + } + 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 ((fd = open(path, smode, perm)) == -1) { rb_raise(rb_eArgError, "Can't open %s", path); } @@ -382,6 +394,9 @@ mm_s_new(argc, argv, obj) } 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); @@ -393,11 +408,11 @@ mm_s_new(argc, argv, obj) offset = 0; if (options != Qnil) { rb_iterate(rb_each, options, mm_i_options, res); - if ((t_mm->size + t_mm->offset) > st.st_size) { + 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->size, t_mm->offset); + t_mm->len, t_mm->offset); } - if (t_mm->size) size = t_mm->size; + if (t_mm->len) size = t_mm->len; offset = t_mm->offset; } init = 0; @@ -409,6 +424,9 @@ mm_s_new(argc, argv, obj) rb_warning("Ignoring offset for an anonymous map"); offset = 0; } + smode = O_RDWR; + pmode = PROT_READ | PROT_WRITE; + t_mm->frozen |= MM_FIXED; } else if (size == 0 && (smode & O_RDWR)) { if (lseek(fd, t_mm->incr - 1, SEEK_END) == -1) { @@ -425,9 +443,11 @@ mm_s_new(argc, argv, obj) if (addr == MAP_FAILED || !addr) { rb_raise(rb_eArgError, "mmap failed (%x)", addr); } +#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; @@ -526,6 +546,7 @@ mm_mprotect(obj, a) return obj; } +#ifdef MADV_NORMAL static VALUE mm_madvise(obj, a) VALUE obj, a; @@ -539,6 +560,7 @@ mm_madvise(obj, a) t_mm->advice = NUM2INT(a); return Qnil; } +#endif #define StringMmap(b, bp, bl) \ do { \ @@ -992,7 +1014,13 @@ mm_slice_bang(argc, argv, str) } buf[i] = rb_str_new(0,0); result = mm_aref_m(argc, buf, str); - mm_aset_m(argc+1, buf, str); +#if RUBY_VERSION_CODE >= 172 + if (!NIL_P(result)) { +#endif + mm_aset_m(argc+1, buf, str); +#if RUBY_VERSION_CODE >= 172 + } +#endif return result; } @@ -1599,11 +1627,13 @@ Init_mmap() 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 @@ -1653,8 +1683,10 @@ Init_mmap() 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); @@ -1,347 +1,188 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> -<HTML> -<HEAD> -<TITLE>mmap.rd</TITLE> -</HEAD> -<BODY> -<H1><A NAME="label:0">Mmap -</A></H1><!-- RDLabel: "Mmap" --> -<P> -<A HREF="ftp://moulon.inra.fr/pub/ruby/">Download</A> -</P> -<P> -The Mmap class implement memory-mapped file objects -</P> -<H3><A NAME="label:1">WARNING -</A></H3><!-- RDLabel: "WARNING" --> -<P> -<EM>The variables $' and $` are not available with gsub! and sub!</EM> -</P> -<H2><A NAME="label:2">SuperClass -</A></H2><!-- RDLabel: "SuperClass" --> -<P> -Object -</P> -<H2><A NAME="label:3">Included Modules -</A></H2><!-- RDLabel: "Included Modules" --> -<UL> -<LI>Comparable -<LI>Enumerable -</UL> -<H2><A NAME="label:4">Class Methods -</A></H2><!-- RDLabel: "Class Methods" --> -<DL> -<DT><A NAME="lockall"><CODE>lockall(<var>flag</var>)</CODE></A><!-- RDLabel: "lockall" --> -<DD> -<P> -disable paging of all pages mapped. <VAR>flag</VAR> can be -<VAR>Mmap::MCL_CURRENT</VAR> or <VAR>Mmap::MCL_FUTURE</VAR> -</P> -</DD> -<DT><A NAME="new"><CODE>new(<var>file</var>, [<var>mode</var> [, <var>protection</var> [, <var>options</var>]]])</CODE></A><!-- RDLabel: "new" --> -<DD> -<P> -create a new object -</P> - -<DL> -<DT><A NAME="label:7"><VAR>file</VAR> -</A><!-- RDLabel: "file" --> -<DD> -<P> -Pathname of the file, if <VAR>nil</VAR> is given an anonymous map -is created <VAR>Mmanp::MAP_ANON</VAR> -</P> -</DD> -<DT><A NAME="label:8"><VAR>mode</VAR> -</A><!-- RDLabel: "mode" --> -<DD> -<P> -Mode to open the file, it can be "r", "w" or "rw" -</P> -</DD> -<DT><A NAME="label:9"><VAR>protection</VAR> -</A><!-- RDLabel: "protection" --> -<DD> -<P> -specify the nature of the mapping -</P> - -<DL> -<DT><A NAME="label:11"><VAR>Mmap::MAP_SHARED</VAR> -</A><!-- RDLabel: "Mmap::MAP_SHARED" --> -<DD> -<P> -Creates a mapping that's shared with all other processes +<?xml version="1.0" ?> +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>mmap.rd</title> +</head> +<body> +<h1><a name="label:0" id="label:0">Mmap</a></h1><!-- RDLabel: "Mmap" --> +<p><a href="ftp://moulon.inra.fr/pub/ruby/">Download</a></p> +<p>The Mmap class implement memory-mapped file objects</p> +<h3><a name="label:1" id="label:1">WARNING</a></h3><!-- RDLabel: "WARNING" --> +<h3><a name="label:2" id="label:2">The variables $' and $` are not available with gsub! and sub!</a></h3><!-- RDLabel: "The variables $' and $` are not available with gsub! and sub!" --> +<h2><a name="label:3" id="label:3">SuperClass</a></h2><!-- RDLabel: "SuperClass" --> +<p>Object</p> +<h2><a name="label:4" id="label:4">Included Modules</a></h2><!-- RDLabel: "Included Modules" --> +<ul> +<li>Comparable</li> +<li>Enumerable</li> +</ul> +<h2><a name="label:5" id="label:5">Class Methods</a></h2><!-- RDLabel: "Class Methods" --> +<dl> +<dt><a name="label:6" id="label:6"><code>lockall(<var>flag</var>)</code></a></dt><!-- RDLabel: "lockall" --> +<dd> +<p>disable paging of all pages mapped. <var>flag</var> can be +<var>Mmap::MCL_CURRENT</var> or <var>Mmap::MCL_FUTURE</var></p></dd> +<dt><a name="label:7" id="label:7"><code>new(<var>file</var>, <var>mode</var> = "<var>r</var>", <var>protection</var> = <var>Mmap</var>::<var>MAP_SHARED</var>, <var>options</var> = {})</code></a><!-- RDLabel: "new" --> +<dt><a name="label:8" id="label:8"><code>new(<var>nil</var>, <var>length</var>, <var>protection</var> = <var>Mmap</var>::<var>MAP_SHARED</var>, <var>options</var> = {})</code></a></dt><!-- RDLabel: "new" --> +<dd> +<p>create a new Mmap object</p> +<dl> +<dt><a name="label:9" id="label:9"><var>file</var> +</a></dt><!-- RDLabel: "file +" --> +<dd> +<p>Pathname of the file, if <var>nil</var> is given an anonymous map +is created <var>Mmanp::MAP_ANON</var></p> +</dd> +<dt><a name="label:10" id="label:10"><var>mode</var> +</a></dt><!-- RDLabel: "mode +" --> +<dd> +<p>Mode to open the file, it can be "r", "w", "rw", "a"</p> +</dd> +<dt><a name="label:11" id="label:11"><var>protection</var> +</a></dt><!-- RDLabel: "protection +" --> +<dd> +<p>specify the nature of the mapping</p> +<dl> +<dt><a name="label:12" id="label:12"><var>Mmap::MAP_SHARED</var> +</a></dt><!-- RDLabel: "Mmap::MAP_SHARED +" --> +<dd> +<p>Creates a mapping that's shared with all other processes mapping the same areas of the file. -The default value is <VAR>Mmap::MAP_SHARED</VAR> -</P> -</DD> -<DT><A NAME="label:12"><VAR>Mmap::MAP_PRIVATE</VAR> -</A><!-- RDLabel: "Mmap::MAP_PRIVATE" --> -<DD> -<P> -Creates a private copy-on-write mapping, so changes to the -contents of the mmap object will be private to this process -</P> -</DD> -</DL> -</DD> -<DT><A NAME="label:10"><VAR>options</VAR> -</A><!-- RDLabel: "options" --> -<DD> -<P> -Hash. If one of the options <VAR>length</VAR> or <VAR>offset</VAR> +The default value is <var>Mmap::MAP_SHARED</var></p> +</dd> +<dt><a name="label:13" id="label:13"><var>Mmap::MAP_PRIVATE</var> +</a></dt><!-- RDLabel: "Mmap::MAP_PRIVATE +" --> +<dd> +<p>Creates a private copy-on-write mapping, so changes to the +contents of the mmap object will be private to this process</p> +</dd> +</dl> +</dd> +<dt><a name="label:14" id="label:14"><var>options</var> +</a></dt><!-- RDLabel: "options +" --> +<dd> +<p>Hash. If one of the options <var>length</var> or <var>offset</var> is specified it will not possible to modify the size of -the mapped file. -</P> - -<DL> -<DT><A NAME="label:13"><VAR>length</VAR> -</A><!-- RDLabel: "length" --> -<DD> -<P> -Maps <VAR>length</VAR> bytes from the file -</P> -</DD> -<DT><A NAME="label:14"><VAR>offset</VAR> -</A><!-- RDLabel: "offset" --> -<DD> -<P> -The mapping begin at <VAR>offset</VAR> -</P> -</DD> -<DT><A NAME="label:15"><VAR>advice</VAR> -</A><!-- RDLabel: "advice" --> -<DD> -<P> -The type of the access (see #madvise) -</P> -</DD> -</DL> -</DD> -</DL> -</DD> -<DT><A NAME="unlockall"><CODE>unlockall</CODE></A><!-- RDLabel: "unlockall" --> -<DD> -<P> -reenable paging -</P> -</DD> -</DL> -<H2><A NAME="label:5">Methods -</A></H2><!-- RDLabel: "Methods" --> -<DL> -<DT><A NAME="extend"><CODE>extend(<var>count</var>)</CODE></A><!-- RDLabel: "extend" --> -<DD> -<P> -add <VAR>count</VAR> bytes to the file (i.e. pre-extend the file) -</P> -</DD> -<DT><A NAME="madvise"><CODE>madvise(<var>advice</var>)</CODE></A><!-- RDLabel: "madvise" --> -<DD> -<P> -<VAR>advice</VAR> can have the value <VAR>Mmap::MADV_NORMAL</VAR>, -<VAR>Mmap::MADV_RANDOM</VAR>, <VAR>Mmap::MADV_SEQUENTIAL</VAR>, -<VAR>Mmap::MADV_WILLNEED</VAR>, <VAR>Mmap::MADV_DONTNEED</VAR> -</P> -</DD> -<DT><A NAME="mprotect"><CODE>mprotect(<var>mode</var>)</CODE></A><!-- RDLabel: "mprotect" --> -<DD> -<P> -change the mode, value must be "r", "w" or "rw" -</P> -</DD> -<DT><A NAME="mlock"><CODE>mlock</CODE></A><!-- RDLabel: "mlock" --> -<DD> -<P> -disable paging -</P> -</DD> -<DT><A NAME="msync"><CODE>msync</CODE></A><!-- RDLabel: "msync" --> -<DT><A NAME="flush"><CODE>flush</CODE></A><!-- RDLabel: "flush" --> -<DD> -<P> -flush the file -</P> -</DD> -<DT><A NAME="munlock"><CODE>munlock</CODE></A><!-- RDLabel: "munlock" --> -<DD> -<P> -reenable paging -</P> -</DD> -<DT><A NAME="munmap"><CODE>munmap</CODE></A><!-- RDLabel: "munmap" --> -<DD> -<P> -terminate the association -</P> -</DD> -</DL> -<H3><A NAME="label:6">Other methods with the same syntax than the methods of <VAR>String</VAR> -</A></H3><!-- RDLabel: "Other methods with the same syntax than the methods ofString" --> -<P> -self == other -</P> -<P> -self > other -</P> -<P> -self >= other -</P> -<P> -self < other -</P> -<P> -self <= other -</P> -<P> -self === other -</P> -<P> -self << other -</P> -<P> -self =~ other -</P> -<P> -self[nth] -</P> -<P> -self[start..last] -</P> -<P> -self[start, length] -</P> -<P> -self[nth] = val -</P> -<P> -self[start..last] = val -</P> -<P> -self[start, len] = val -</P> -<P> -self <=> other -</P> -<P> -<<(other) -</P> -<P> -casecmp(other) >= 1.7.1 -</P> -<P> -concat(other) -</P> -<P> -capitalize! -</P> -<P> -chop! -</P> -<P> -chomp!([rs]) -</P> -<P> -count(o1 [, o2, ...]) -</P> -<P> -crypt(salt) -</P> -<P> -delete!(str) -</P> -<P> -downcase! -</P> -<P> -each_byte {|char|...} -</P> -<P> -each([rs]) {|line|...} -</P> -<P> -each_line([rs]) {|line|...} -</P> -<P> -empty? -</P> -<P> -freeze -</P> -<P> -frozen -</P> -<P> -gsub!(pattern, replace) -</P> -<P> -gsub!(pattern) {...} -</P> -<P> -include?(other) -</P> -<P> -index(substr[, pos]) -</P> -<P> -insert(index, str) >= 1.7.1 -</P> -<P> -length -</P> -<P> -reverse! -</P> -<P> -rindex(substr[, pos]) -</P> -<P> -scan(pattern) -</P> -<P> -scan(pattern) {...} -</P> -<P> -size -</P> -<P> -slice -</P> -<P> -slice! -</P> -<P> -split([sep[, limit]]) -</P> -<P> -squeeze!([str]) -</P> -<P> -strip! -</P> -<P> -sub!(pattern, replace) -</P> -<P> -sub!(pattern) {...} -</P> -<P> -sum([bits]) -</P> -<P> -swapcase! -</P> -<P> -tr!(search, replace) -</P> -<P> -tr_s!(search, replace) -</P> -<P> -upcase! -</P> +the mapped file.</p> +<dl> +<dt><a name="label:15" id="label:15"><var>length</var> +</a></dt><!-- RDLabel: "length +" --> +<dd> +<p>Maps <var>length</var> bytes from the file</p> +</dd> +<dt><a name="label:16" id="label:16"><var>offset</var> +</a></dt><!-- RDLabel: "offset +" --> +<dd> +<p>The mapping begin at <var>offset</var></p> +</dd> +<dt><a name="label:17" id="label:17"><var>advice</var> +</a></dt><!-- RDLabel: "advice +" --> +<dd> +<p>The type of the access (see #madvise)</p> +</dd> +</dl> +</dd> +</dl></dd> +<dt><a name="label:18" id="label:18"><code>unlockall</code></a></dt><!-- RDLabel: "unlockall" --> +<dd> +<p>reenable paging</p></dd> +</dl> +<h2><a name="label:19" id="label:19">Methods</a></h2><!-- RDLabel: "Methods" --> +<dl> +<dt><a name="label:20" id="label:20"><code>extend(<var>count</var>)</code></a></dt><!-- RDLabel: "extend" --> +<dd> +<p>add <var>count</var> bytes to the file (i.e. pre-extend the file) </p></dd> +<dt><a name="label:21" id="label:21"><code>madvise(<var>advice</var>)</code></a></dt><!-- RDLabel: "madvise" --> +<dd> +<p><var>advice</var> can have the value <var>Mmap::MADV_NORMAL</var>, +<var>Mmap::MADV_RANDOM</var>, <var>Mmap::MADV_SEQUENTIAL</var>, +<var>Mmap::MADV_WILLNEED</var>, <var>Mmap::MADV_DONTNEED</var></p></dd> +<dt><a name="label:22" id="label:22"><code>mprotect(<var>mode</var>)</code></a></dt><!-- RDLabel: "mprotect" --> +<dd> +<p>change the mode, value must be "r", "w" or "rw"</p></dd> +<dt><a name="label:23" id="label:23"><code>mlock</code></a></dt><!-- RDLabel: "mlock" --> +<dd> +<p>disable paging</p></dd> +<dt><a name="label:24" id="label:24"><code>msync</code></a><!-- RDLabel: "msync" --> +<dt><a name="label:25" id="label:25"><code>flush</code></a></dt><!-- RDLabel: "flush" --> +<dd> +<p>flush the file</p></dd> +<dt><a name="label:26" id="label:26"><code>munlock</code></a></dt><!-- RDLabel: "munlock" --> +<dd> +<p>reenable paging</p></dd> +<dt><a name="label:27" id="label:27"><code>munmap</code></a></dt><!-- RDLabel: "munmap" --> +<dd> +<p>terminate the association</p></dd> +</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!" --> +</dl> -</BODY> -</HTML> +</body> +</html> @@ -3,10 +3,12 @@ ((<Download|URL:ftp://moulon.inra.fr/pub/ruby/>)) +#^ The Mmap class implement memory-mapped file objects === WARNING -((*The variables $' and $` are not available with gsub! and sub!*)) +=== The variables $' and $` are not available with gsub! and sub! +#^ == SuperClass @@ -16,15 +18,19 @@ Object * Comparable * Enumerable - +# class Mmap +# include Comparable +# include Enumerable +# class << self == Class Methods --- lockall(flag) disable paging of all pages mapped. ((|flag|)) can be ((|Mmap::MCL_CURRENT|)) or ((|Mmap::MCL_FUTURE|)) ---- new(file, [mode [, protection [, options]]]) - create a new object +--- new(file, mode = "r", protection = Mmap::MAP_SHARED, options = {}) +--- new(nil, length, protection = Mmap::MAP_SHARED, options = {}) + create a new Mmap object : ((|file|)) Pathname of the file, if ((|nil|)) is given an anonymous map @@ -63,6 +69,7 @@ Object --- unlockall reenable paging +# end == Methods --- extend(count) @@ -89,114 +96,115 @@ Object --- munmap terminate the association -=== Other methods with the same syntax than the methods of ((|String|)) +=== Other methods with the same syntax than for the class String + -self == other +--- self == other -self > other +--- self > other -self >= other +--- self >= other -self < other +--- self < other -self <= other +--- self <= other -self === other +--- self === other -self << other +--- self << other -self =~ other +--- self =~ other -self[nth] +--- self[nth] -self[start..last] +--- self[start..last] -self[start, length] +--- self[start, length] -self[nth] = val +--- self[nth] = val -self[start..last] = val +--- self[start..last] = val -self[start, len] = val +--- self[start, len] = val -self <=> other +--- self <=> other -<<(other) +--- <<(other) -casecmp(other) >= 1.7.1 +--- casecmp(other) >= 1.7.1 -concat(other) +--- concat(other) -capitalize! +--- capitalize! -chop! +--- chop! -chomp!([rs]) +--- chomp!([rs]) -count(o1 [, o2, ...]) +--- count(o1 [, o2, ...]) -crypt(salt) +--- crypt(salt) -delete!(str) +--- delete!(str) -downcase! +--- downcase! -each_byte {|char|...} +--- each_byte {|char|...} -each([rs]) {|line|...} +--- each([rs]) {|line|...} -each_line([rs]) {|line|...} +--- each_line([rs]) {|line|...} -empty? +--- empty? -freeze +--- freeze -frozen +--- frozen -gsub!(pattern, replace) +--- gsub!(pattern, replace) -gsub!(pattern) {...} +--- gsub!(pattern) {|str|...} -include?(other) +--- include?(other) -index(substr[, pos]) +--- index(substr[, pos]) -insert(index, str) >= 1.7.1 +--- insert(index, str) >= 1.7.1 -length +--- length -reverse! +--- reverse! -rindex(substr[, pos]) +--- rindex(substr[, pos]) -scan(pattern) +--- scan(pattern) -scan(pattern) {...} +--- scan(pattern) {|str| ...} -size +--- size -slice +--- slice -slice! +--- slice! -split([sep[, limit]]) +--- split([sep[, limit]]) -squeeze!([str]) +--- squeeze!([str]) -strip! +--- strip! -sub!(pattern, replace) +--- sub!(pattern, replace) -sub!(pattern) {...} +--- sub!(pattern) {|str| ...} -sum([bits]) +--- sum([bits]) -swapcase! +--- swapcase! -tr!(search, replace) +--- tr!(search, replace) -tr_s!(search, replace) +--- tr_s!(search, replace) -upcase! +--- upcase! =end diff --git a/tests/mmapt.rb b/tests/mmapt.rb index a7a049c..c6a1fdc 100644 --- a/tests/mmapt.rb +++ b/tests/mmapt.rb @@ -2,17 +2,12 @@ $LOAD_PATH.unshift *%w{.. . tests} require 'mmap' require 'ftools' -begin - require 'test/unit' - Inh = Test::Unit -rescue LoadError - require 'runit/testcase' - require 'runit/cui/testrunner' - Inh = RUNIT -end +require 'runit_' $mmap, $str = nil, nil +Inh = defined?(RUNIT) ? RUNIT : Test::Unit + class TestMmap < Inh::TestCase def internal_init $mmap.unmap if $mmap @@ -70,7 +65,7 @@ class TestMmap < Inh::TestCase eval "$mmap#{access}" rescue IndexError, RangeError else - assert_fail("*must* fail with IndexError") + flunk("*must* fail with IndexError") end else eval "$mmap#{access}" @@ -114,7 +109,7 @@ class TestMmap < Inh::TestCase eval "$mmap#{access}" rescue IndexError, RangeError else - assert_fail("*must* fail with IndexError") + flunk("*must* fail with IndexError") end else eval "$mmap#{access}" diff --git a/tests/runit_.rb b/tests/runit_.rb new file mode 100644 index 0000000..0479592 --- /dev/null +++ b/tests/runit_.rb @@ -0,0 +1,44 @@ +begin + require 'test/unit' +rescue LoadError + require 'runit/testcase' + require 'runit/cui/testrunner' + + module RUNIT + module Assert + def assert_raises(error, message = nil) + begin + yield + rescue error + assert(true, message) + rescue + assert_fail("must fail with #{error} : #{string}") + else + assert_fail("*must* fail : #{string}") + end + end + def flunk(message = "") + assert_fail(message) + end + end + end +end + + +if RUBY_VERSION > "1.7" + class Array + alias indices select + end + class Hash + alias indexes select + end + module BDB + class Common + alias indexes select + end + + class Recnum + alias indices select + end + end +end |