mmap2 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Changes +55 -0
- data/README.rdoc +36 -0
- data/b.rb +33 -0
- data/ext/mmap/extconf.rb +22 -0
- data/ext/mmap/mmap.c +2606 -0
- data/lib/mmap/version.rb +5 -0
- data/lib/mmap.rb +21 -0
- data/mmap.rd +253 -0
- data/test/test_mmap.rb +373 -0
- metadata +60 -0
data/lib/mmap/version.rb
ADDED
data/lib/mmap.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# The Mmap class implement memory-mapped file objects
|
2
|
+
#
|
3
|
+
# Most of these methods have the same syntax than the methods of String
|
4
|
+
#
|
5
|
+
# === WARNING
|
6
|
+
# === The variables $' and $` are not available with gsub! and sub!
|
7
|
+
require 'mmap/mmap' unless defined? Mmap
|
8
|
+
require 'mmap/version'
|
9
|
+
|
10
|
+
class Mmap
|
11
|
+
include Comparable
|
12
|
+
include Enumerable
|
13
|
+
|
14
|
+
def clone # :nodoc:
|
15
|
+
raise TypeError, "can't clone instance of #{self.class}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def dup # :nodoc:
|
19
|
+
raise TypeError, "can't dup instance of #{self.class}"
|
20
|
+
end
|
21
|
+
end
|
data/mmap.rd
ADDED
@@ -0,0 +1,253 @@
|
|
1
|
+
=begin
|
2
|
+
= Mmap
|
3
|
+
|
4
|
+
((<Download|URL:ftp://moulon.inra.fr/pub/ruby/>))
|
5
|
+
|
6
|
+
The Mmap class implement memory-mapped file objects
|
7
|
+
|
8
|
+
=== WARNING
|
9
|
+
=== The variables $' and $` are not available with gsub! and sub!
|
10
|
+
|
11
|
+
== SuperClass
|
12
|
+
|
13
|
+
Object
|
14
|
+
|
15
|
+
== Included Modules
|
16
|
+
|
17
|
+
* Comparable
|
18
|
+
* Enumerable
|
19
|
+
|
20
|
+
== Class Methods
|
21
|
+
|
22
|
+
--- lockall(flag)
|
23
|
+
disable paging of all pages mapped. ((|flag|)) can be
|
24
|
+
((|Mmap::MCL_CURRENT|)) or ((|Mmap::MCL_FUTURE|))
|
25
|
+
|
26
|
+
--- new(file, mode = "r", protection = Mmap::MAP_SHARED, options = {})
|
27
|
+
--- new(nil, length, protection = Mmap::MAP_SHARED, options = {})
|
28
|
+
create a new Mmap object
|
29
|
+
|
30
|
+
: ((|file|))
|
31
|
+
Pathname of the file, if ((|nil|)) is given an anonymous map
|
32
|
+
is created ((|Mmanp::MAP_ANON|))
|
33
|
+
|
34
|
+
: ((|mode|))
|
35
|
+
Mode to open the file, it can be "r", "w", "rw", "a"
|
36
|
+
|
37
|
+
: ((|protection|))
|
38
|
+
specify the nature of the mapping
|
39
|
+
|
40
|
+
: ((|Mmap::MAP_SHARED|))
|
41
|
+
Creates a mapping that's shared with all other processes
|
42
|
+
mapping the same areas of the file.
|
43
|
+
The default value is ((|Mmap::MAP_SHARED|))
|
44
|
+
|
45
|
+
: ((|Mmap::MAP_PRIVATE|))
|
46
|
+
Creates a private copy-on-write mapping, so changes to the
|
47
|
+
contents of the mmap object will be private to this process
|
48
|
+
|
49
|
+
: ((|options|))
|
50
|
+
Hash. If one of the options ((|length|)) or ((|offset|))
|
51
|
+
is specified it will not possible to modify the size of
|
52
|
+
the mapped file.
|
53
|
+
|
54
|
+
: ((|length|))
|
55
|
+
Maps ((|length|)) bytes from the file
|
56
|
+
|
57
|
+
: ((|offset|))
|
58
|
+
The mapping begin at ((|offset|))
|
59
|
+
|
60
|
+
: ((|advice|))
|
61
|
+
The type of the access (see #madvise)
|
62
|
+
|
63
|
+
|
64
|
+
--- unlockall
|
65
|
+
reenable paging
|
66
|
+
|
67
|
+
== Methods
|
68
|
+
|
69
|
+
--- extend(count)
|
70
|
+
add ((|count|)) bytes to the file (i.e. pre-extend the file)
|
71
|
+
|
72
|
+
--- madvise(advice)
|
73
|
+
((|advice|)) can have the value ((|Mmap::MADV_NORMAL|)),
|
74
|
+
((|Mmap::MADV_RANDOM|)), ((|Mmap::MADV_SEQUENTIAL|)),
|
75
|
+
((|Mmap::MADV_WILLNEED|)), ((|Mmap::MADV_DONTNEED|))
|
76
|
+
|
77
|
+
--- mprotect(mode)
|
78
|
+
change the mode, value must be "r", "w" or "rw"
|
79
|
+
|
80
|
+
--- mlock
|
81
|
+
disable paging
|
82
|
+
|
83
|
+
--- msync
|
84
|
+
--- flush
|
85
|
+
flush the file
|
86
|
+
|
87
|
+
--- munlock
|
88
|
+
reenable paging
|
89
|
+
|
90
|
+
--- munmap
|
91
|
+
terminate the association
|
92
|
+
|
93
|
+
=== Other methods with the same syntax than for the class String
|
94
|
+
|
95
|
+
|
96
|
+
--- self == other
|
97
|
+
comparison
|
98
|
+
|
99
|
+
--- self > other
|
100
|
+
comparison
|
101
|
+
|
102
|
+
--- self >= other
|
103
|
+
comparison
|
104
|
+
|
105
|
+
--- self < other
|
106
|
+
comparison
|
107
|
+
|
108
|
+
--- self <= other
|
109
|
+
comparison
|
110
|
+
|
111
|
+
--- self === other
|
112
|
+
used for ((|case|)) comparison
|
113
|
+
|
114
|
+
--- self << other
|
115
|
+
append ((|other|)) to ((|self|))
|
116
|
+
|
117
|
+
--- self =~ other
|
118
|
+
return an index of the match
|
119
|
+
|
120
|
+
--- self[nth]
|
121
|
+
retrieve the ((|nth|)) character
|
122
|
+
|
123
|
+
--- self[start..last]
|
124
|
+
return a substring from ((|start|)) to ((|last|))
|
125
|
+
|
126
|
+
--- self[start, length]
|
127
|
+
return a substring of ((|lenght|)) characters from ((|start|))
|
128
|
+
|
129
|
+
--- self[nth] = val
|
130
|
+
change the ((|nth|)) character with ((|val|))
|
131
|
+
|
132
|
+
--- self[start..last] = val
|
133
|
+
change substring from ((|start|)) to ((|last|)) with ((|val|))
|
134
|
+
|
135
|
+
--- self[start, len] = val
|
136
|
+
replace ((|length|)) characters from ((|start|)) with ((|val|)).
|
137
|
+
|
138
|
+
--- self <=> other
|
139
|
+
comparison : return -1, 0, 1
|
140
|
+
|
141
|
+
--- casecmp(other) >= 1.7.1
|
142
|
+
|
143
|
+
--- concat(other)
|
144
|
+
append the contents of ((|other|))
|
145
|
+
|
146
|
+
--- capitalize!
|
147
|
+
change the first character to uppercase letter
|
148
|
+
|
149
|
+
--- chop!
|
150
|
+
chop off the last character
|
151
|
+
|
152
|
+
--- chomp!([rs])
|
153
|
+
chop off the line ending character, specified by ((|rs|))
|
154
|
+
|
155
|
+
--- count(o1 [, o2, ...])
|
156
|
+
each parameter defines a set of character to count
|
157
|
+
|
158
|
+
--- crypt(salt)
|
159
|
+
crypt with ((|salt|))
|
160
|
+
|
161
|
+
--- delete!(str)
|
162
|
+
delete every characters included in ((|str|))
|
163
|
+
|
164
|
+
--- downcase!
|
165
|
+
change all uppercase character to lowercase character
|
166
|
+
|
167
|
+
--- each_byte {|char|...}
|
168
|
+
iterate on each byte
|
169
|
+
|
170
|
+
--- each([rs]) {|line|...}
|
171
|
+
--- each_line([rs]) {|line|...}
|
172
|
+
iterate on each line
|
173
|
+
|
174
|
+
--- empty?
|
175
|
+
return ((|true|)) if the file is empty
|
176
|
+
|
177
|
+
--- freeze
|
178
|
+
freeze the current file
|
179
|
+
|
180
|
+
--- frozen
|
181
|
+
return ((|true|)) if the file is frozen
|
182
|
+
|
183
|
+
--- gsub!(pattern, replace)
|
184
|
+
global substitution
|
185
|
+
|
186
|
+
--- gsub!(pattern) {|str|...}
|
187
|
+
global substitution
|
188
|
+
|
189
|
+
--- include?(other)
|
190
|
+
return ((|true|)) if ((|other|)) is found
|
191
|
+
|
192
|
+
--- index(substr[, pos])
|
193
|
+
return the index of ((|substr|))
|
194
|
+
|
195
|
+
--- insert(index, str) >= 1.7.1
|
196
|
+
insert ((|str|)) at ((|index|))
|
197
|
+
|
198
|
+
--- length
|
199
|
+
return the size of the file
|
200
|
+
|
201
|
+
--- reverse!
|
202
|
+
reverse the content of the file
|
203
|
+
|
204
|
+
--- rindex(substr[, pos])
|
205
|
+
return the index of the last occurrence of ((|substr|))
|
206
|
+
|
207
|
+
--- scan(pattern)
|
208
|
+
return an array of all occurence matched by ((|pattern|))
|
209
|
+
|
210
|
+
--- scan(pattern) {|str| ...}
|
211
|
+
iterate through the file, matching the ((|pattern|))
|
212
|
+
|
213
|
+
--- size
|
214
|
+
return the size of the file
|
215
|
+
|
216
|
+
--- slice
|
217
|
+
same than ((|[]|))
|
218
|
+
|
219
|
+
--- slice!
|
220
|
+
delete the specified portion of the file
|
221
|
+
|
222
|
+
--- split([sep[, limit]])
|
223
|
+
splits into a list of strings and return this array
|
224
|
+
|
225
|
+
--- squeeze!([str])
|
226
|
+
squeezes sequences of the same characters which is included in ((|str|))
|
227
|
+
|
228
|
+
--- strip!
|
229
|
+
removes leading and trailing whitespace
|
230
|
+
|
231
|
+
--- sub!(pattern, replace)
|
232
|
+
substitution
|
233
|
+
|
234
|
+
--- sub!(pattern) {|str| ...}
|
235
|
+
substitution
|
236
|
+
|
237
|
+
--- sum([bits])
|
238
|
+
return a checksum
|
239
|
+
|
240
|
+
--- swapcase!
|
241
|
+
replaces all lowercase characters to uppercase characters, and vice-versa
|
242
|
+
|
243
|
+
--- tr!(search, replace)
|
244
|
+
translate the character from ((|search|)) to ((|replace|))
|
245
|
+
|
246
|
+
--- tr_s!(search, replace)
|
247
|
+
translate the character from ((|search|)) to ((|replace|)), then
|
248
|
+
squeeze sequence of the same characters
|
249
|
+
|
250
|
+
--- upcase!
|
251
|
+
replaces all lowercase characters to downcase characters
|
252
|
+
|
253
|
+
=end
|
data/test/test_mmap.rb
ADDED
@@ -0,0 +1,373 @@
|
|
1
|
+
require 'mmap'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
|
6
|
+
class TestMmap < Minitest::Test
|
7
|
+
EXT_DIR = File.expand_path(File.join(File.dirname(__FILE__), '..', 'ext', 'mmap'))
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@tmp = Dir.tmpdir
|
11
|
+
FileUtils.cp(File.join(EXT_DIR, 'mmap.c'), @tmp)
|
12
|
+
|
13
|
+
@mmap_c = File.join(@tmp, 'mmap.c')
|
14
|
+
|
15
|
+
@mmap = Mmap.new(@mmap_c, "rw")
|
16
|
+
@str = File.read @mmap_c
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
@mmap.unmap
|
21
|
+
aa = File.join(@tmp, 'aa')
|
22
|
+
bb = File.join(@tmp, 'bb')
|
23
|
+
FileUtils.rm(aa) if File.exist?(aa)
|
24
|
+
FileUtils.rm(bb) if File.exist?(bb)
|
25
|
+
end
|
26
|
+
|
27
|
+
def internal_read
|
28
|
+
File.readlines(@mmap_c, nil)[0]
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_inspect
|
32
|
+
assert @mmap.inspect
|
33
|
+
end
|
34
|
+
|
35
|
+
# Make sure clone raises. Cloning would be bad.
|
36
|
+
def test_clone
|
37
|
+
assert_raises(TypeError) do
|
38
|
+
@mmap.clone
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Make sure dup raises. Cloning would be bad.
|
43
|
+
def test_dup
|
44
|
+
assert_raises(TypeError) do
|
45
|
+
@mmap.dup
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_length
|
50
|
+
assert_equal(@mmap.length, @str.length, "<lenght>")
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_simple_aref
|
54
|
+
assert_equal(@str[10], @mmap[10], "<aref>");
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_aref
|
58
|
+
max = @str.size * 2
|
59
|
+
72.times do
|
60
|
+
ran1 = rand(max)
|
61
|
+
assert_equal(@str[ran1], @mmap[ran1], "<aref>");
|
62
|
+
assert_equal(@str[-ran1], @mmap[-ran1], "<aref>");
|
63
|
+
ran2 = rand(max)
|
64
|
+
assert_equal(@str[ran1, ran2], @mmap[ran1, ran2], "<double aref>");
|
65
|
+
assert_equal(@str[-ran1, ran2], @mmap[-ran1, ran2], "<double aref>");
|
66
|
+
assert_equal(@str[ran1, -ran2], @mmap[ran1, -ran2], "<double aref>");
|
67
|
+
assert_equal(@str[-ran1, -ran2], @mmap[-ran1, -ran2], "<double aref>");
|
68
|
+
assert_equal(@str[ran1 .. ran2], @mmap[ran1 .. ran2], "<double aref>");
|
69
|
+
assert_equal(@str[-ran1 .. ran2], @mmap[-ran1 .. ran2], "<double aref>");
|
70
|
+
assert_equal(@str[ran1 .. -ran2], @mmap[ran1 .. -ran2], "<double aref>");
|
71
|
+
assert_equal(@str[-ran1 .. -ran2], @mmap[-ran1 .. -ran2], "<double aref>");
|
72
|
+
end
|
73
|
+
assert_equal(@str[/random/], @mmap[/random/], "<aref regexp>")
|
74
|
+
assert_equal(@str[/real/], @mmap[/real/], "<aref regexp>")
|
75
|
+
assert_equal(@str[/none/], @mmap[/none/], "<aref regexp>")
|
76
|
+
end
|
77
|
+
|
78
|
+
def internal_aset(a, b = nil, c = true)
|
79
|
+
access = if b
|
80
|
+
repl = ''
|
81
|
+
rand(12).times do
|
82
|
+
repl << (65 + rand(25))
|
83
|
+
end
|
84
|
+
if c
|
85
|
+
"[a, b] = '#{repl}'"
|
86
|
+
else
|
87
|
+
"[a .. b] = '#{repl}'"
|
88
|
+
end
|
89
|
+
else
|
90
|
+
"[a] = #{(65 + rand(25))}.chr"
|
91
|
+
end
|
92
|
+
begin
|
93
|
+
eval "@str#{access}"
|
94
|
+
rescue IndexError, RangeError
|
95
|
+
begin
|
96
|
+
eval "@mmap#{access}"
|
97
|
+
rescue IndexError, RangeError
|
98
|
+
else
|
99
|
+
flunk("*must* fail with IndexError")
|
100
|
+
end
|
101
|
+
else
|
102
|
+
eval "@mmap#{access}"
|
103
|
+
end
|
104
|
+
assert_equal(@mmap.to_str, @str, "<internal aset>")
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_aset
|
108
|
+
@mmap[/...../] = "change it"
|
109
|
+
@str[/...../] = "change it"
|
110
|
+
assert_equal(@mmap.to_str, @str, "aset regexp")
|
111
|
+
@mmap["ge i"] = "change it"
|
112
|
+
@str["ge i"] = "change it"
|
113
|
+
assert_equal(@mmap.to_str, @str, "aset regexp")
|
114
|
+
max = @str.size * 2
|
115
|
+
72.times do
|
116
|
+
ran1 = rand(max)
|
117
|
+
internal_aset(ran1)
|
118
|
+
internal_aset(-ran1)
|
119
|
+
ran2 = rand(max)
|
120
|
+
internal_aset(ran1, ran2)
|
121
|
+
internal_aset(ran1, -ran2)
|
122
|
+
internal_aset(-ran1, ran2)
|
123
|
+
internal_aset(-ran1, -ran2)
|
124
|
+
internal_aset(ran1, ran2, false)
|
125
|
+
internal_aset(ran1, -ran2, false)
|
126
|
+
internal_aset(-ran1, ran2, false)
|
127
|
+
internal_aset(-ran1, -ran2, false)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def internal_slice(a, b = nil, c = true)
|
132
|
+
access = if b
|
133
|
+
if c
|
134
|
+
".slice!(a, b)"
|
135
|
+
else
|
136
|
+
".slice!(a .. b)"
|
137
|
+
end
|
138
|
+
else
|
139
|
+
".slice!(a)"
|
140
|
+
end
|
141
|
+
begin
|
142
|
+
eval "@str#{access}"
|
143
|
+
rescue IndexError, RangeError
|
144
|
+
begin
|
145
|
+
eval "@mmap#{access}"
|
146
|
+
rescue IndexError, RangeError
|
147
|
+
else
|
148
|
+
flunk("*must* fail with IndexError")
|
149
|
+
end
|
150
|
+
else
|
151
|
+
eval "@mmap#{access}"
|
152
|
+
end
|
153
|
+
assert_equal(@mmap.to_str, @str, "<internal aset>")
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_slice
|
157
|
+
max = @str.size * 2
|
158
|
+
72.times do
|
159
|
+
ran1 = rand(max)
|
160
|
+
internal_slice(ran1)
|
161
|
+
internal_slice(-ran1)
|
162
|
+
ran2 = rand(max)
|
163
|
+
internal_slice(ran1, ran2)
|
164
|
+
internal_slice(ran1, -ran2)
|
165
|
+
internal_slice(-ran1, ran2)
|
166
|
+
internal_slice(-ran1, -ran2)
|
167
|
+
internal_slice(ran1, ran2, false)
|
168
|
+
internal_slice(ran1, -ran2, false)
|
169
|
+
internal_slice(-ran1, ran2, false)
|
170
|
+
internal_slice(-ran1, -ran2, false)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_easy_sub!
|
175
|
+
assert_equal(@mmap.index("rb_raise"), @mmap.index("rb_raise"), "<index>")
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_reg
|
179
|
+
assert_equal(@str.scan(/include/), @mmap.scan(/include/), "<scan>")
|
180
|
+
assert_equal(@mmap.index("rb_raise"), @mmap.index("rb_raise"), "<index>")
|
181
|
+
assert_equal(@mmap.rindex("rb_raise"), @mmap.rindex("rb_raise"), "<rindex>")
|
182
|
+
assert_equal(@mmap.index(/rb_raise/), @mmap.index(/rb_raise/), "<index>")
|
183
|
+
assert_equal(@mmap.rindex(/rb_raise/), @mmap.rindex(/rb_raise/), "<rindex>")
|
184
|
+
('a' .. 'z').each do |i|
|
185
|
+
assert_equal(@mmap.index(i), @str.index(i), "<index>")
|
186
|
+
assert_equal(@mmap.rindex(i), @str.rindex(i), "<rindex>")
|
187
|
+
assert_equal(@mmap.index(i), @str.index(/#{i}/), "<index>")
|
188
|
+
assert_equal(@mmap.rindex(i), @str.rindex(/#{i}/), "<rindex>")
|
189
|
+
end
|
190
|
+
@mmap.sub!(/GetMmap/, 'XXXX'); @str.sub!(/GetMmap/, 'XXXX')
|
191
|
+
assert_equal(@str, @mmap.to_str, "<after sub!>")
|
192
|
+
@mmap.gsub!(/GetMmap/, 'XXXX'); @str.gsub!(/GetMmap/, 'XXXX')
|
193
|
+
assert_equal(@mmap.to_str, @str, "<after gsub!>")
|
194
|
+
@mmap.gsub!(/YYYY/, 'XXXX'); @str.gsub!(/YYYY/, 'XXXX')
|
195
|
+
assert_equal(@mmap.to_str, @str, "<after gsub!>")
|
196
|
+
assert_equal(@mmap.split(/\w+/), @str.split(/\w+/), "<split>")
|
197
|
+
assert_equal(@mmap.split(/\W+/), @str.split(/\W+/), "<split>")
|
198
|
+
assert_equal(@mmap.crypt("abc"), @str.crypt("abc"), "<crypt>")
|
199
|
+
end
|
200
|
+
|
201
|
+
def internal_modify idmod, *args
|
202
|
+
if res = @str.method(idmod)[*args]
|
203
|
+
assert_equal(@mmap.method(idmod)[*args].to_str, res, "<#{idmod}>")
|
204
|
+
else
|
205
|
+
assert_equal(@mmap.method(idmod)[*args], res, "<#{idmod}>")
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_modify
|
210
|
+
skip "pending"
|
211
|
+
internal_modify(:reverse!)
|
212
|
+
internal_modify(:upcase!)
|
213
|
+
internal_modify(:downcase!)
|
214
|
+
internal_modify(:capitalize!)
|
215
|
+
internal_modify(:swapcase!)
|
216
|
+
internal_modify(:strip!)
|
217
|
+
internal_modify(:chop!)
|
218
|
+
internal_modify(:chomp!)
|
219
|
+
internal_modify(:squeeze!)
|
220
|
+
internal_modify(:tr!, 'abcdefghi', '123456789')
|
221
|
+
internal_modify(:tr_s!, 'jklmnopqr', '123456789')
|
222
|
+
internal_modify(:delete!, 'A-Z')
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_iterate
|
226
|
+
mmap = []; @mmap.each_byte {|l| mmap << l}
|
227
|
+
str = []; @str.each_byte {|l| str << l}
|
228
|
+
assert_equal(mmap, str, "<each_byte>")
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_concat
|
232
|
+
[@mmap, @str].each {|l| l << "bc"; l << 12; l << "ab"}
|
233
|
+
assert_equal(@mmap.to_str, @str, "<<")
|
234
|
+
assert_raises(TypeError) { @mmap << 456 }
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_extend
|
238
|
+
@mmap.extend(4096)
|
239
|
+
assert_equal(@mmap.to_str, @str, "extend")
|
240
|
+
if @str.respond_to?(:insert)
|
241
|
+
10.times do
|
242
|
+
pos = rand(@mmap.size)
|
243
|
+
str = "XX" * rand(66)
|
244
|
+
@str.insert(pos, str)
|
245
|
+
@mmap.insert(pos, str)
|
246
|
+
assert_equal(@mmap.to_str, @str, "insert")
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_msync
|
252
|
+
3.times do |i|
|
253
|
+
[@mmap, @str].each {|l| l << "x" * 4096 }
|
254
|
+
str = internal_read
|
255
|
+
if str != @mmap.to_str
|
256
|
+
@mmap.msync
|
257
|
+
assert_equal(@mmap.to_str, internal_read, "msync")
|
258
|
+
break
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_protect
|
264
|
+
assert_equal(@mmap, @mmap.protect("w"), "protect")
|
265
|
+
assert_equal("a", @mmap[12] = "a", "affect")
|
266
|
+
@str[12] = "a"
|
267
|
+
assert_equal(@mmap.to_str, @str, "protect")
|
268
|
+
assert_raises(TypeError) { @mmap << "a" }
|
269
|
+
assert_equal(@mmap, @mmap.protect("r"), "protect")
|
270
|
+
assert_raises(RuntimeError) { @mmap[12] = "a" }
|
271
|
+
assert_raises(RuntimeError) { @mmap.protect("rw") }
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_anonymous
|
275
|
+
if defined?(Mmap::MAP_ANONYMOUS)
|
276
|
+
assert_kind_of(Mmap, @mmap =
|
277
|
+
Mmap.new(nil, "length" => 8192, "offset" => 12,
|
278
|
+
"increment" => 1024, "initialize" => " "))
|
279
|
+
@str = " " * 8192
|
280
|
+
1024.times do
|
281
|
+
pos = rand(8192)
|
282
|
+
@mmap[pos] = @str[pos] = (32 + rand(64)).chr
|
283
|
+
end
|
284
|
+
assert_equal(@mmap.to_str, @str, "insert anonymous")
|
285
|
+
assert_raises(IndexError) { @mmap[12345] = "a" }
|
286
|
+
assert_raises(TypeError) { @mmap << "a" }
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_fileno
|
291
|
+
@mmap = Mmap.new(File.new(@mmap_c, "r+"), "rw")
|
292
|
+
test_aref
|
293
|
+
@mmap[12] = "3"; @str[12] = "3"
|
294
|
+
assert_equal(@mmap.to_str, @str, "insert io")
|
295
|
+
assert_equal(0, @mmap <=> @str, "cmp")
|
296
|
+
assert_raises(TypeError) { @mmap[12] = "ab" }
|
297
|
+
@mmap.freeze
|
298
|
+
if @str.respond_to?(:match)
|
299
|
+
assert_equal(@str.match("rb_match_busy").offset(0),
|
300
|
+
@mmap.match("rb_match_busy").offset(0), "match")
|
301
|
+
assert_equal(@str.match(/rb_../).offset(0),
|
302
|
+
@mmap.match(/rb_../).offset(0), "match")
|
303
|
+
assert_equal(@str.match("rb_match_buzy"),
|
304
|
+
@mmap.match("rb_match_buzy"), "no match")
|
305
|
+
assert_equal(@str =~ /rb_match_busy/,
|
306
|
+
@mmap =~ /rb_match_busy/, "match")
|
307
|
+
assert_equal(@str =~ /rb_match_buzy/,
|
308
|
+
@mmap =~ /rb_match_buzy/, "no match")
|
309
|
+
end
|
310
|
+
assert_raises(RuntimeError) { @mmap[12] = "a" }
|
311
|
+
end
|
312
|
+
|
313
|
+
def test_div
|
314
|
+
string = "azertyuiopqsdfghjklm"
|
315
|
+
assert_kind_of(Mmap, m0 = Mmap.new("#{@tmp}/aa", "a"), "new a")
|
316
|
+
File.open("#{@tmp}/bb", "w") {|f| f.puts "aaa" }
|
317
|
+
assert_kind_of(Mmap, m1 = Mmap.new("#{@tmp}/bb", "w"), "new a")
|
318
|
+
assert_equal(true, m0.empty?, "empty")
|
319
|
+
assert_equal(true, m1.empty?, "empty")
|
320
|
+
assert_equal(m0, m0 << string, "<<")
|
321
|
+
assert_equal(m1, m1 << string, "<<")
|
322
|
+
assert_equal(false, m0.empty?, "empty")
|
323
|
+
assert_equal(false, m1.empty?, "empty")
|
324
|
+
assert_equal(true, m0 == m1, "==")
|
325
|
+
if string.respond_to?(:casecmp)
|
326
|
+
assert_equal(0, m0.casecmp(string.upcase), "casecmp")
|
327
|
+
assert_equal(0, m0.casecmp(m1), "casecmp")
|
328
|
+
end
|
329
|
+
assert_equal(true, m0 === m1, "===")
|
330
|
+
assert_equal(false, m0 === string, "===")
|
331
|
+
assert_equal(true, m0.eql?(m1), ".eql?")
|
332
|
+
assert_equal(true, m1.eql?(m0), ".eql?")
|
333
|
+
assert_equal(false, m1.eql?(string), ".eql?")
|
334
|
+
assert_equal(m0.hash, m1.hash, "hash")
|
335
|
+
assert_equal(true, m0.include?("azert"), "include")
|
336
|
+
assert_equal(false, m1.include?("aqert"), "include")
|
337
|
+
i = 0
|
338
|
+
m0.scan(/./) {|c| assert_equal(c, string[i,1], "scan"); i += 1}
|
339
|
+
assert_nil(m0.munmap, "munmap")
|
340
|
+
assert_nil(m1.munmap, "munmap")
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_other
|
344
|
+
test_div
|
345
|
+
if File.exist?("#{@tmp}/aa")
|
346
|
+
string = "azertyuiopqsdfghjklm"
|
347
|
+
assert_kind_of(Mmap, m0 = Mmap.new("#{@tmp}/aa", "r"), "new r")
|
348
|
+
assert_equal(string, m0.to_str, "content")
|
349
|
+
assert_raises(RuntimeError) { m0[0] = 12 }
|
350
|
+
assert_raises(RuntimeError) { m0 << 12 }
|
351
|
+
assert_nil(m0.munmap, "munmap")
|
352
|
+
if defined?(Mmap::MAP_ANONYMOUS)
|
353
|
+
assert_raises(ArgumentError) { Mmap.new(nil, "w") }
|
354
|
+
assert_kind_of(Mmap, m0 = Mmap.new(nil, 12), "new w")
|
355
|
+
assert_equal(false, m0.empty?, "empty")
|
356
|
+
assert_equal("a", m0[0] = "a", "set")
|
357
|
+
assert_raises(TypeError) { m0 << 12 }
|
358
|
+
if defined?(Mmap::MADV_DONTNEED)
|
359
|
+
assert_nil(m0.advise(Mmap::MADV_DONTNEED), "advise")
|
360
|
+
assert_equal("a", m0[0,1], "get")
|
361
|
+
end
|
362
|
+
assert_equal(m0, m0.sub!(/./) { "y" }, "sub")
|
363
|
+
assert_equal(m0, m0.gsub!(/./) { "x" }, "gsub")
|
364
|
+
assert_equal("x" * 12, m0.to_str, "retrieve")
|
365
|
+
assert_equal("ab", m0[1..2] = "ab", "range")
|
366
|
+
assert_raises(TypeError) { m0[1..2] = "abc" }
|
367
|
+
assert_raises(ArgumentError) { m0.lock }
|
368
|
+
assert_raises(ArgumentError) { Mmap::lockall(0) }
|
369
|
+
assert_nil(m0.munmap, "munmap")
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mmap2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.2.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Guy Decoux
|
8
|
+
- Aaron Patterson
|
9
|
+
- Kevin Lyda
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2017-02-15 00:00:00.000000000 Z
|
14
|
+
dependencies: []
|
15
|
+
description: The Mmap class implement memory-mapped file objects for Ruby 2.x
|
16
|
+
email:
|
17
|
+
- ts@moulon.inra.fr
|
18
|
+
- tenderlove@github.com
|
19
|
+
- lyda@gitlab.com
|
20
|
+
executables: []
|
21
|
+
extensions:
|
22
|
+
- ext/mmap/extconf.rb
|
23
|
+
extra_rdoc_files: []
|
24
|
+
files:
|
25
|
+
- Changes
|
26
|
+
- README.rdoc
|
27
|
+
- b.rb
|
28
|
+
- ext/mmap/extconf.rb
|
29
|
+
- ext/mmap/mmap.c
|
30
|
+
- lib/mmap.rb
|
31
|
+
- lib/mmap/version.rb
|
32
|
+
- mmap.rd
|
33
|
+
- test/test_mmap.rb
|
34
|
+
homepage: https://gitlab.com/lyda/mmap
|
35
|
+
licenses:
|
36
|
+
- Ruby
|
37
|
+
metadata: {}
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 2.5.1
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: The Mmap class
|
58
|
+
test_files:
|
59
|
+
- b.rb
|
60
|
+
- test/test_mmap.rb
|