mmap 0.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.
- data/Changes +55 -0
- data/Manifest.txt +11 -0
- data/README.rdoc +36 -0
- data/Rakefile +27 -0
- data/b.rb +33 -0
- data/ext/mmap/extconf.rb +32 -0
- data/ext/mmap/mmap.c +2624 -0
- data/lib/mmap.rb +22 -0
- data/mmap.html +272 -0
- data/mmap.rd +253 -0
- data/test/test_mmap.rb +367 -0
- metadata +88 -0
data/Changes
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
-- 0.1.2
|
3
|
+
|
4
|
+
* fixed some bugs (options & new) (Thanks Joseph McDonald <joe@vpop.net>)
|
5
|
+
* added anonymous map
|
6
|
+
* added mlock, munlock, etc
|
7
|
+
|
8
|
+
-- 0.1.3
|
9
|
+
|
10
|
+
* added #count, #slice, #slice!
|
11
|
+
* added #insert, #casecmp (>= 171)
|
12
|
+
* corrected NEW2LONG
|
13
|
+
|
14
|
+
-- 0.1.4
|
15
|
+
|
16
|
+
* added #lstrip!, #rstrip! for 1.7.1
|
17
|
+
* corrected strip!
|
18
|
+
* corrected mm_bang_i (reverse!, etc)
|
19
|
+
* added a small test (make test)
|
20
|
+
|
21
|
+
-- 0.1.5
|
22
|
+
|
23
|
+
* added str[/a(a)/, 1] for 1.7.1
|
24
|
+
* corrected mm_aset (mm_update(str, ...))
|
25
|
+
* corrected ==, ===, eql?
|
26
|
+
* corrected mm_sub_bang, mm_gsub_bang (to_str)
|
27
|
+
|
28
|
+
-- 0.1.6
|
29
|
+
|
30
|
+
* adapted for 1.7.2 (mm_str)
|
31
|
+
* corrected real for mm_sub_bang
|
32
|
+
* protected against old class
|
33
|
+
|
34
|
+
-- 0.1.7
|
35
|
+
|
36
|
+
* 1.7.2 (::allocate, #initialize)
|
37
|
+
* added "a" for ::new
|
38
|
+
* experimental EXP_INCR_SIZE (4096) ("increment" => 4096)
|
39
|
+
* tests for RUNIT/Test::Unit
|
40
|
+
|
41
|
+
-- 0.1.8
|
42
|
+
|
43
|
+
* test for madvise(2)
|
44
|
+
* don't test size for MAP_ANON
|
45
|
+
* added syntax Mmap(nil, length)
|
46
|
+
* documentation : make rd2; make rdoc
|
47
|
+
|
48
|
+
-- 0.1.9
|
49
|
+
|
50
|
+
* String#slice! was modified in 1.6.8
|
51
|
+
* added ::new(IO)
|
52
|
+
|
53
|
+
--- 0.2.0
|
54
|
+
|
55
|
+
* adapted for 1.8.0
|
data/Manifest.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
= Mmap
|
2
|
+
|
3
|
+
* http://rubyforge.org/frs/?group_id=8350
|
4
|
+
|
5
|
+
== DESCRIPTION
|
6
|
+
|
7
|
+
The Mmap class implement memory-mapped file objects
|
8
|
+
|
9
|
+
== SYNOPSIS
|
10
|
+
|
11
|
+
require 'mmap'
|
12
|
+
|
13
|
+
mmap = Mmap.new(__FILE__)
|
14
|
+
mmap.advise(Mmap::MADV_SEQUENTIAL)
|
15
|
+
|
16
|
+
mmap.each do |line|
|
17
|
+
puts line
|
18
|
+
end
|
19
|
+
|
20
|
+
== Installation
|
21
|
+
|
22
|
+
gem install mmap
|
23
|
+
|
24
|
+
== Documentation
|
25
|
+
|
26
|
+
rake docs
|
27
|
+
|
28
|
+
== Copying
|
29
|
+
|
30
|
+
This extension module is copyrighted free software by Guy Decoux
|
31
|
+
|
32
|
+
You can redistribute it and/or modify it under the same term as
|
33
|
+
Ruby.
|
34
|
+
|
35
|
+
|
36
|
+
Guy Decoux <ts@moulon.inra.fr>
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
|
6
|
+
gem 'rake-compiler', '>= 0.4.1'
|
7
|
+
require "rake/extensiontask"
|
8
|
+
|
9
|
+
HOE = Hoe.spec 'mmap' do
|
10
|
+
developer('Guy Decoux', 'ts@moulon.inra.fr')
|
11
|
+
self.readme_file = 'README.rdoc'
|
12
|
+
self.history_file = 'Changes'
|
13
|
+
self.extra_rdoc_files = FileList['*.rdoc']
|
14
|
+
|
15
|
+
%w{ rake-compiler }.each do |dep|
|
16
|
+
self.extra_dev_deps << [dep, '>= 0']
|
17
|
+
end
|
18
|
+
|
19
|
+
self.spec_extras = { :extensions => ["ext/mmap/extconf.rb"] }
|
20
|
+
end
|
21
|
+
|
22
|
+
RET = Rake::ExtensionTask.new("mmap", HOE.spec) do |ext|
|
23
|
+
ext.lib_dir = File.join('lib', 'mmap')
|
24
|
+
end
|
25
|
+
|
26
|
+
# vim: syntax=ruby
|
27
|
+
|
data/b.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
$LOAD_PATH.unshift "."
|
3
|
+
require "mmap"
|
4
|
+
PAGESIZE = 4096
|
5
|
+
f = File.open("aa", "w")
|
6
|
+
f.write("\0" * PAGESIZE)
|
7
|
+
f.write("b.rb")
|
8
|
+
f.write("\0" * PAGESIZE)
|
9
|
+
f.close
|
10
|
+
m = Mmap.new("aa", "w", "offset" => 0)
|
11
|
+
p m.size == "b.rb".size + 2 * PAGESIZE
|
12
|
+
p m.scan(/[a-z.]+/) == ["b.rb"]
|
13
|
+
p m.index("b.rb") == PAGESIZE
|
14
|
+
p m.rindex("b.rb") == PAGESIZE
|
15
|
+
p m.sub!(/[a-z.]+/, "toto") == m
|
16
|
+
p m.scan(/[a-z.]+/) == ["toto"]
|
17
|
+
begin
|
18
|
+
m.sub!(/[a-z.]+/, "alpha")
|
19
|
+
puts "not OK must give an error"
|
20
|
+
rescue
|
21
|
+
puts "OK : #$!"
|
22
|
+
end
|
23
|
+
m.munmap
|
24
|
+
m = Mmap.new("aa", "rw")
|
25
|
+
p m.index("toto") == PAGESIZE
|
26
|
+
p m.sub!(/([a-z.]+)/, "alpha") == m
|
27
|
+
p $& == "toto"
|
28
|
+
p $1 == "toto"
|
29
|
+
p m.index("toto") == nil
|
30
|
+
p m.index("alpha") == PAGESIZE
|
31
|
+
p m.size == 5 + 2 * PAGESIZE
|
32
|
+
m.gsub!(/\0/, "X")
|
33
|
+
p m.size == 5 + 2 * PAGESIZE
|
data/ext/mmap/extconf.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
ARGV.collect! {|x| x.sub(/^--with-mmap-prefix=/, "--with-mmap-dir=") }
|
3
|
+
|
4
|
+
require 'mkmf'
|
5
|
+
|
6
|
+
if unknown = enable_config("unknown")
|
7
|
+
libs = if CONFIG.key?("LIBRUBYARG_STATIC")
|
8
|
+
Config::expand(CONFIG["LIBRUBYARG_STATIC"].dup).sub(/^-l/, '')
|
9
|
+
else
|
10
|
+
Config::expand(CONFIG["LIBRUBYARG"].dup).sub(/^lib([^.]*).*/, '\\1')
|
11
|
+
end
|
12
|
+
unknown = find_library(libs, "ruby_init",
|
13
|
+
Config::expand(CONFIG["archdir"].dup))
|
14
|
+
end
|
15
|
+
|
16
|
+
dir_config("mmap")
|
17
|
+
|
18
|
+
["lstrip", "match", "insert", "casecmp"].each do |func|
|
19
|
+
if "aa".respond_to?(func)
|
20
|
+
$CFLAGS += " -DHAVE_RB_STR_#{func.upcase}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
if enable_config("ipc")
|
25
|
+
unless have_func("semctl") && have_func("shmctl")
|
26
|
+
$stderr.puts "\tIPC will not be available"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
$CFLAGS += " -DRUBYLIBDIR='\"#{CONFIG['rubylibdir']}\"'"
|
31
|
+
|
32
|
+
create_makefile "mmap"
|
data/ext/mmap/mmap.c
ADDED
@@ -0,0 +1,2624 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <fcntl.h>
|
3
|
+
#include <ctype.h>
|
4
|
+
#include <sys/types.h>
|
5
|
+
#include <sys/stat.h>
|
6
|
+
#include <unistd.h>
|
7
|
+
#include <sys/mman.h>
|
8
|
+
|
9
|
+
#if HAVE_SEMCTL && HAVE_SHMCTL
|
10
|
+
#include <sys/shm.h>
|
11
|
+
#include <sys/ipc.h>
|
12
|
+
#include <sys/sem.h>
|
13
|
+
#endif
|
14
|
+
|
15
|
+
#include <rubyio.h>
|
16
|
+
#include <intern.h>
|
17
|
+
#include <re.h>
|
18
|
+
|
19
|
+
#ifndef StringValue
|
20
|
+
#define StringValue(x) do { \
|
21
|
+
if (TYPE(x) != T_STRING) x = rb_str_to_str(x); \
|
22
|
+
} while (0)
|
23
|
+
#endif
|
24
|
+
|
25
|
+
#ifndef StringValuePtr
|
26
|
+
#define StringValuePtr(x) STR2CSTR(x)
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#ifndef SafeStringValue
|
30
|
+
#define SafeStringValue(x) Check_SafeStr(x)
|
31
|
+
#endif
|
32
|
+
|
33
|
+
#ifndef MADV_NORMAL
|
34
|
+
#ifdef POSIX_MADV_NORMAL
|
35
|
+
#define MADV_NORMAL POSIX_MADV_NORMAL
|
36
|
+
#define MADV_RANDOM POSIX_MADV_RANDOM
|
37
|
+
#define MADV_SEQUENTIAL POSIX_MADV_SEQUENTIAL
|
38
|
+
#define MADV_WILLNEED POSIX_MADV_WILLNEED
|
39
|
+
#define MADV_DONTNEED POSIX_MADV_DONTNEED
|
40
|
+
#define madvise posix_madvise
|
41
|
+
#endif
|
42
|
+
#endif
|
43
|
+
|
44
|
+
#define BEG(no) regs->beg[no]
|
45
|
+
#define END(no) regs->end[no]
|
46
|
+
|
47
|
+
#ifndef MMAP_RETTYPE
|
48
|
+
#ifndef _POSIX_C_SOURCE
|
49
|
+
#define _POSIX_C_SOURCE 199309
|
50
|
+
#endif /* !_POSIX_C_SOURCE */
|
51
|
+
#ifdef _POSIX_VERSION
|
52
|
+
#if _POSIX_VERSION >= 199309
|
53
|
+
#define MMAP_RETTYPE void *
|
54
|
+
#endif /* _POSIX_VERSION >= 199309 */
|
55
|
+
#endif /* _POSIX_VERSION */
|
56
|
+
#endif /* !MMAP_RETTYPE */
|
57
|
+
|
58
|
+
#ifndef MMAP_RETTYPE
|
59
|
+
#define MMAP_RETTYPE caddr_t
|
60
|
+
#endif
|
61
|
+
|
62
|
+
#ifndef MAP_FAILED
|
63
|
+
#define MAP_FAILED ((caddr_t)-1)
|
64
|
+
#endif /* !MAP_FAILED */
|
65
|
+
|
66
|
+
#ifndef MAP_ANON
|
67
|
+
#ifdef MAP_ANONYMOUS
|
68
|
+
#define MAP_ANON MAP_ANONYMOUS
|
69
|
+
#endif
|
70
|
+
#endif
|
71
|
+
|
72
|
+
static VALUE mm_cMap;
|
73
|
+
|
74
|
+
#define EXP_INCR_SIZE 4096
|
75
|
+
|
76
|
+
typedef struct {
|
77
|
+
MMAP_RETTYPE addr;
|
78
|
+
int smode, pmode, vscope;
|
79
|
+
int advice, flag;
|
80
|
+
VALUE key;
|
81
|
+
int semid, shmid;
|
82
|
+
size_t len, real, incr;
|
83
|
+
off_t offset;
|
84
|
+
char *path, *template;
|
85
|
+
} mm_mmap;
|
86
|
+
|
87
|
+
typedef struct {
|
88
|
+
int count;
|
89
|
+
mm_mmap *t;
|
90
|
+
} mm_ipc;
|
91
|
+
|
92
|
+
typedef struct {
|
93
|
+
VALUE obj, *argv;
|
94
|
+
int flag, id, argc;
|
95
|
+
} mm_bang;
|
96
|
+
|
97
|
+
#define MM_MODIFY 1
|
98
|
+
#define MM_ORIGIN 2
|
99
|
+
#define MM_CHANGE (MM_MODIFY | 4)
|
100
|
+
#define MM_PROTECT 8
|
101
|
+
|
102
|
+
#define MM_FROZEN (1<<0)
|
103
|
+
#define MM_FIXED (1<<1)
|
104
|
+
#define MM_ANON (1<<2)
|
105
|
+
#define MM_LOCK (1<<3)
|
106
|
+
#define MM_IPC (1<<4)
|
107
|
+
#define MM_TMP (1<<5)
|
108
|
+
|
109
|
+
#if HAVE_SEMCTL && HAVE_SHMCTL
|
110
|
+
static char template[1024];
|
111
|
+
|
112
|
+
union semun
|
113
|
+
{
|
114
|
+
int val;
|
115
|
+
struct semid_ds *buf;
|
116
|
+
unsigned short int *array;
|
117
|
+
struct seminfo *__buf;
|
118
|
+
};
|
119
|
+
#endif
|
120
|
+
|
121
|
+
static void
|
122
|
+
mm_free(i_mm)
|
123
|
+
mm_ipc *i_mm;
|
124
|
+
{
|
125
|
+
#if HAVE_SEMCTL && HAVE_SHMCTL
|
126
|
+
if (i_mm->t->flag & MM_IPC) {
|
127
|
+
struct shmid_ds buf;
|
128
|
+
|
129
|
+
if (shmctl(i_mm->t->shmid, IPC_STAT, &buf) != -1) {
|
130
|
+
if (buf.shm_nattch == 1 && (i_mm->t->flag & MM_TMP)) {
|
131
|
+
semctl(i_mm->t->semid, 0, IPC_RMID);
|
132
|
+
if (i_mm->t->template) {
|
133
|
+
unlink(i_mm->t->template);
|
134
|
+
free(i_mm->t->template);
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
shmdt(i_mm->t);
|
139
|
+
}
|
140
|
+
else {
|
141
|
+
free(i_mm->t);
|
142
|
+
}
|
143
|
+
#endif
|
144
|
+
if (i_mm->t->path) {
|
145
|
+
munmap(i_mm->t->addr, i_mm->t->len);
|
146
|
+
if (i_mm->t->path != (char *)-1) {
|
147
|
+
if (i_mm->t->real < i_mm->t->len && i_mm->t->vscope != MAP_PRIVATE &&
|
148
|
+
truncate(i_mm->t->path, i_mm->t->real) == -1) {
|
149
|
+
free(i_mm->t->path);
|
150
|
+
free(i_mm);
|
151
|
+
rb_raise(rb_eTypeError, "truncate");
|
152
|
+
}
|
153
|
+
free(i_mm->t->path);
|
154
|
+
}
|
155
|
+
}
|
156
|
+
free(i_mm);
|
157
|
+
}
|
158
|
+
|
159
|
+
static void
|
160
|
+
mm_lock(i_mm, wait_lock)
|
161
|
+
mm_ipc *i_mm;
|
162
|
+
int wait_lock;
|
163
|
+
{
|
164
|
+
#if HAVE_SEMCTL && HAVE_SHMCTL
|
165
|
+
struct sembuf sem_op;
|
166
|
+
|
167
|
+
if (i_mm->t->flag & MM_IPC) {
|
168
|
+
i_mm->count++;
|
169
|
+
if (i_mm->count == 1) {
|
170
|
+
retry:
|
171
|
+
sem_op.sem_num = 0;
|
172
|
+
sem_op.sem_op = -1;
|
173
|
+
sem_op.sem_flg = IPC_NOWAIT;
|
174
|
+
if (semop(i_mm->t->semid, &sem_op, 1) == -1) {
|
175
|
+
if (errno == EAGAIN) {
|
176
|
+
if (!wait_lock) {
|
177
|
+
rb_raise(rb_const_get(rb_mErrno, rb_intern("EAGAIN")), "EAGAIN");
|
178
|
+
}
|
179
|
+
rb_thread_sleep(1);
|
180
|
+
goto retry;
|
181
|
+
}
|
182
|
+
rb_sys_fail("semop()");
|
183
|
+
}
|
184
|
+
}
|
185
|
+
}
|
186
|
+
#endif
|
187
|
+
}
|
188
|
+
|
189
|
+
static void
|
190
|
+
mm_unlock(i_mm)
|
191
|
+
mm_ipc *i_mm;
|
192
|
+
{
|
193
|
+
#if HAVE_SEMCTL && HAVE_SHMCTL
|
194
|
+
struct sembuf sem_op;
|
195
|
+
|
196
|
+
if (i_mm->t->flag & MM_IPC) {
|
197
|
+
i_mm->count--;
|
198
|
+
if (!i_mm->count) {
|
199
|
+
retry:
|
200
|
+
sem_op.sem_num = 0;
|
201
|
+
sem_op.sem_op = 1;
|
202
|
+
sem_op.sem_flg = IPC_NOWAIT;
|
203
|
+
if (semop(i_mm->t->semid, &sem_op, 1) == -1) {
|
204
|
+
if (errno == EAGAIN) {
|
205
|
+
rb_thread_sleep(1);
|
206
|
+
goto retry;
|
207
|
+
}
|
208
|
+
rb_sys_fail("semop()");
|
209
|
+
}
|
210
|
+
}
|
211
|
+
}
|
212
|
+
#endif
|
213
|
+
}
|
214
|
+
|
215
|
+
#define GetMmap(obj, i_mm, t_modify) \
|
216
|
+
Data_Get_Struct(obj, mm_ipc, i_mm); \
|
217
|
+
if (!i_mm->t->path) { \
|
218
|
+
rb_raise(rb_eIOError, "unmapped file"); \
|
219
|
+
} \
|
220
|
+
if ((t_modify & MM_MODIFY) && (i_mm->t->flag & MM_FROZEN)) { \
|
221
|
+
rb_error_frozen("mmap"); \
|
222
|
+
}
|
223
|
+
|
224
|
+
static VALUE
|
225
|
+
mm_vunlock(obj)
|
226
|
+
VALUE obj;
|
227
|
+
{
|
228
|
+
mm_ipc *i_mm;
|
229
|
+
|
230
|
+
GetMmap(obj, i_mm, 0);
|
231
|
+
mm_unlock(i_mm);
|
232
|
+
return Qnil;
|
233
|
+
}
|
234
|
+
|
235
|
+
/*
|
236
|
+
* call-seq: semlock
|
237
|
+
*
|
238
|
+
* Create a lock
|
239
|
+
*/
|
240
|
+
static VALUE
|
241
|
+
mm_semlock(argc, argv, obj)
|
242
|
+
int argc;
|
243
|
+
VALUE *argv, obj;
|
244
|
+
{
|
245
|
+
mm_ipc *i_mm;
|
246
|
+
|
247
|
+
GetMmap(obj, i_mm, 0);
|
248
|
+
if (!(i_mm->t->flag & MM_IPC)) {
|
249
|
+
rb_warning("useless use of #semlock");
|
250
|
+
rb_yield(obj);
|
251
|
+
}
|
252
|
+
else {
|
253
|
+
#if HAVE_SEMCTL && HAVE_SHMCTL
|
254
|
+
VALUE a;
|
255
|
+
int wait_lock = Qtrue;
|
256
|
+
|
257
|
+
if (rb_scan_args(argc, argv, "01", &a)) {
|
258
|
+
wait_lock = RTEST(a);
|
259
|
+
}
|
260
|
+
mm_lock(i_mm, wait_lock);
|
261
|
+
rb_ensure(rb_yield, obj, mm_vunlock, obj);
|
262
|
+
#endif
|
263
|
+
}
|
264
|
+
return Qnil;
|
265
|
+
}
|
266
|
+
|
267
|
+
/*
|
268
|
+
* call-seq: ipc_key
|
269
|
+
*
|
270
|
+
* Get the ipc key
|
271
|
+
*/
|
272
|
+
static VALUE
|
273
|
+
mm_ipc_key(obj)
|
274
|
+
VALUE obj;
|
275
|
+
{
|
276
|
+
mm_ipc *i_mm;
|
277
|
+
|
278
|
+
GetMmap(obj, i_mm, 0);
|
279
|
+
if (i_mm->t->flag & MM_IPC) {
|
280
|
+
return INT2NUM(i_mm->t->key);
|
281
|
+
}
|
282
|
+
return INT2NUM(-1);
|
283
|
+
}
|
284
|
+
|
285
|
+
/*
|
286
|
+
* Document-method: munmap
|
287
|
+
* Document-method: unmap
|
288
|
+
*
|
289
|
+
* call-seq: munmap
|
290
|
+
*
|
291
|
+
* terminate the association
|
292
|
+
*/
|
293
|
+
static VALUE
|
294
|
+
mm_unmap(obj)
|
295
|
+
VALUE obj;
|
296
|
+
{
|
297
|
+
mm_ipc *i_mm;
|
298
|
+
|
299
|
+
GetMmap(obj, i_mm, 0);
|
300
|
+
if (i_mm->t->path) {
|
301
|
+
mm_lock(i_mm, Qtrue);
|
302
|
+
munmap(i_mm->t->addr, i_mm->t->len);
|
303
|
+
if (i_mm->t->path != (char *)-1) {
|
304
|
+
if (i_mm->t->real < i_mm->t->len && i_mm->t->vscope != MAP_PRIVATE &&
|
305
|
+
truncate(i_mm->t->path, i_mm->t->real) == -1) {
|
306
|
+
rb_raise(rb_eTypeError, "truncate");
|
307
|
+
}
|
308
|
+
free(i_mm->t->path);
|
309
|
+
}
|
310
|
+
i_mm->t->path = '\0';
|
311
|
+
mm_unlock(i_mm);
|
312
|
+
}
|
313
|
+
return Qnil;
|
314
|
+
}
|
315
|
+
|
316
|
+
/*
|
317
|
+
* call-seq: freeze
|
318
|
+
*
|
319
|
+
* freeze the current file
|
320
|
+
*/
|
321
|
+
static VALUE
|
322
|
+
mm_freeze(obj)
|
323
|
+
VALUE obj;
|
324
|
+
{
|
325
|
+
mm_ipc *i_mm;
|
326
|
+
rb_obj_freeze(obj);
|
327
|
+
GetMmap(obj, i_mm, 0);
|
328
|
+
i_mm->t->flag |= MM_FROZEN;
|
329
|
+
return obj;
|
330
|
+
}
|
331
|
+
|
332
|
+
static VALUE
|
333
|
+
mm_str(obj, modify)
|
334
|
+
VALUE obj;
|
335
|
+
int modify;
|
336
|
+
{
|
337
|
+
mm_ipc *i_mm;
|
338
|
+
VALUE ret = Qnil;
|
339
|
+
|
340
|
+
GetMmap(obj, i_mm, modify & ~MM_ORIGIN);
|
341
|
+
if (modify & MM_MODIFY) {
|
342
|
+
if (i_mm->t->flag & MM_FROZEN) rb_error_frozen("mmap");
|
343
|
+
if (!OBJ_TAINTED(ret) && rb_safe_level() >= 4)
|
344
|
+
rb_raise(rb_eSecurityError, "Insecure: can't modify mmap");
|
345
|
+
}
|
346
|
+
#if HAVE_RB_DEFINE_ALLOC_FUNC
|
347
|
+
ret = rb_obj_alloc(rb_cString);
|
348
|
+
if (rb_obj_tainted(obj)) {
|
349
|
+
OBJ_TAINT(ret);
|
350
|
+
}
|
351
|
+
#else
|
352
|
+
if (rb_obj_tainted(obj)) {
|
353
|
+
ret = rb_tainted_str_new2("");
|
354
|
+
}
|
355
|
+
else {
|
356
|
+
ret = rb_str_new2("");
|
357
|
+
}
|
358
|
+
free(RSTRING(ret)->ptr);
|
359
|
+
#endif
|
360
|
+
RSTRING(ret)->ptr = i_mm->t->addr;
|
361
|
+
RSTRING(ret)->len = i_mm->t->real;
|
362
|
+
if (modify & MM_ORIGIN) {
|
363
|
+
#if HAVE_RB_DEFINE_ALLOC_FUNC
|
364
|
+
RSTRING(ret)->aux.shared = ret;
|
365
|
+
FL_SET(ret, ELTS_SHARED);
|
366
|
+
#else
|
367
|
+
RSTRING(ret)->orig = ret;
|
368
|
+
#endif
|
369
|
+
}
|
370
|
+
if (i_mm->t->flag & MM_FROZEN) {
|
371
|
+
ret = rb_obj_freeze(ret);
|
372
|
+
}
|
373
|
+
return ret;
|
374
|
+
}
|
375
|
+
|
376
|
+
/*
|
377
|
+
* call-seq: to_str
|
378
|
+
*
|
379
|
+
* Convert object to a string
|
380
|
+
*/
|
381
|
+
static VALUE
|
382
|
+
mm_to_str(obj)
|
383
|
+
VALUE obj;
|
384
|
+
{
|
385
|
+
return mm_str(obj, MM_ORIGIN);
|
386
|
+
}
|
387
|
+
|
388
|
+
extern char *ruby_strdup();
|
389
|
+
|
390
|
+
typedef struct {
|
391
|
+
mm_ipc *i_mm;
|
392
|
+
size_t len;
|
393
|
+
} mm_st;
|
394
|
+
|
395
|
+
static VALUE
|
396
|
+
mm_i_expand(st_mm)
|
397
|
+
mm_st *st_mm;
|
398
|
+
{
|
399
|
+
int fd;
|
400
|
+
mm_ipc *i_mm = st_mm->i_mm;
|
401
|
+
size_t len = st_mm->len;
|
402
|
+
|
403
|
+
if (munmap(i_mm->t->addr, i_mm->t->len)) {
|
404
|
+
rb_raise(rb_eArgError, "munmap failed");
|
405
|
+
}
|
406
|
+
if ((fd = open(i_mm->t->path, i_mm->t->smode)) == -1) {
|
407
|
+
rb_raise(rb_eArgError, "Can't open %s", i_mm->t->path);
|
408
|
+
}
|
409
|
+
if (len > i_mm->t->len) {
|
410
|
+
if (lseek(fd, len - i_mm->t->len - 1, SEEK_END) == -1) {
|
411
|
+
rb_raise(rb_eIOError, "Can't lseek %d", len - i_mm->t->len - 1);
|
412
|
+
}
|
413
|
+
if (write(fd, "\000", 1) != 1) {
|
414
|
+
rb_raise(rb_eIOError, "Can't extend %s", i_mm->t->path);
|
415
|
+
}
|
416
|
+
}
|
417
|
+
else if (len < i_mm->t->len && truncate(i_mm->t->path, len) == -1) {
|
418
|
+
rb_raise(rb_eIOError, "Can't truncate %s", i_mm->t->path);
|
419
|
+
}
|
420
|
+
i_mm->t->addr = mmap(0, len, i_mm->t->pmode, i_mm->t->vscope, fd, i_mm->t->offset);
|
421
|
+
close(fd);
|
422
|
+
if (i_mm->t->addr == MAP_FAILED) {
|
423
|
+
rb_raise(rb_eArgError, "mmap failed");
|
424
|
+
}
|
425
|
+
#ifdef MADV_NORMAL
|
426
|
+
if (i_mm->t->advice && madvise(i_mm->t->addr, len, i_mm->t->advice) == -1) {
|
427
|
+
rb_raise(rb_eArgError, "madvise(%d)", errno);
|
428
|
+
}
|
429
|
+
#endif
|
430
|
+
if ((i_mm->t->flag & MM_LOCK) && mlock(i_mm->t->addr, len) == -1) {
|
431
|
+
rb_raise(rb_eArgError, "mlock(%d)", errno);
|
432
|
+
}
|
433
|
+
i_mm->t->len = len;
|
434
|
+
return Qnil;
|
435
|
+
}
|
436
|
+
|
437
|
+
static void
|
438
|
+
mm_expandf(i_mm, len)
|
439
|
+
mm_ipc *i_mm;
|
440
|
+
size_t len;
|
441
|
+
{
|
442
|
+
int status;
|
443
|
+
mm_st st_mm;
|
444
|
+
|
445
|
+
if (i_mm->t->vscope == MAP_PRIVATE) {
|
446
|
+
rb_raise(rb_eTypeError, "expand for a private map");
|
447
|
+
}
|
448
|
+
if (i_mm->t->flag & MM_FIXED) {
|
449
|
+
rb_raise(rb_eTypeError, "expand for a fixed map");
|
450
|
+
}
|
451
|
+
if (!i_mm->t->path || i_mm->t->path == (char *)-1) {
|
452
|
+
rb_raise(rb_eTypeError, "expand for an anonymous map");
|
453
|
+
}
|
454
|
+
st_mm.i_mm = i_mm;
|
455
|
+
st_mm.len = len;
|
456
|
+
if (i_mm->t->flag & MM_IPC) {
|
457
|
+
mm_lock(i_mm, Qtrue);
|
458
|
+
rb_protect(mm_i_expand, (VALUE)&st_mm, &status);
|
459
|
+
mm_unlock(i_mm);
|
460
|
+
if (status) {
|
461
|
+
rb_jump_tag(status);
|
462
|
+
}
|
463
|
+
}
|
464
|
+
else {
|
465
|
+
mm_i_expand(&st_mm);
|
466
|
+
}
|
467
|
+
}
|
468
|
+
|
469
|
+
static void
|
470
|
+
mm_realloc(i_mm, len)
|
471
|
+
mm_ipc *i_mm;
|
472
|
+
size_t len;
|
473
|
+
{
|
474
|
+
if (i_mm->t->flag & MM_FROZEN) rb_error_frozen("mmap");
|
475
|
+
if (len > i_mm->t->len) {
|
476
|
+
if ((len - i_mm->t->len) < i_mm->t->incr) {
|
477
|
+
len = i_mm->t->len + i_mm->t->incr;
|
478
|
+
}
|
479
|
+
mm_expandf(i_mm, len);
|
480
|
+
}
|
481
|
+
}
|
482
|
+
|
483
|
+
/*
|
484
|
+
* call-seq:
|
485
|
+
* extend(count)
|
486
|
+
*
|
487
|
+
* add <em>count</em> bytes to the file (i.e. pre-extend the file)
|
488
|
+
*/
|
489
|
+
static VALUE
|
490
|
+
mm_extend(obj, a)
|
491
|
+
VALUE obj, a;
|
492
|
+
{
|
493
|
+
mm_ipc *i_mm;
|
494
|
+
long len;
|
495
|
+
|
496
|
+
GetMmap(obj, i_mm, MM_MODIFY);
|
497
|
+
len = NUM2LONG(a);
|
498
|
+
if (len > 0) {
|
499
|
+
mm_expandf(i_mm, i_mm->t->len + len);
|
500
|
+
}
|
501
|
+
return UINT2NUM(i_mm->t->len);
|
502
|
+
}
|
503
|
+
|
504
|
+
static VALUE
|
505
|
+
mm_i_options(arg, obj)
|
506
|
+
VALUE arg, obj;
|
507
|
+
{
|
508
|
+
mm_ipc *i_mm;
|
509
|
+
char *options;
|
510
|
+
VALUE key, value;
|
511
|
+
|
512
|
+
Data_Get_Struct(obj, mm_ipc, i_mm);
|
513
|
+
key = rb_ary_entry(arg, 0);
|
514
|
+
value = rb_ary_entry(arg, 1);
|
515
|
+
key = rb_obj_as_string(key);
|
516
|
+
options = StringValuePtr(key);
|
517
|
+
if (strcmp(options, "length") == 0) {
|
518
|
+
i_mm->t->len = NUM2UINT(value);
|
519
|
+
if (i_mm->t->len <= 0) {
|
520
|
+
rb_raise(rb_eArgError, "Invalid value for length %d", i_mm->t->len);
|
521
|
+
}
|
522
|
+
i_mm->t->flag |= MM_FIXED;
|
523
|
+
}
|
524
|
+
else if (strcmp(options, "offset") == 0) {
|
525
|
+
i_mm->t->offset = NUM2INT(value);
|
526
|
+
if (i_mm->t->offset < 0) {
|
527
|
+
rb_raise(rb_eArgError, "Invalid value for offset %d", i_mm->t->offset);
|
528
|
+
}
|
529
|
+
i_mm->t->flag |= MM_FIXED;
|
530
|
+
}
|
531
|
+
else if (strcmp(options, "advice") == 0) {
|
532
|
+
i_mm->t->advice = NUM2INT(value);
|
533
|
+
}
|
534
|
+
else if (strcmp(options, "increment") == 0) {
|
535
|
+
int incr = NUM2INT(value);
|
536
|
+
if (incr < 0) {
|
537
|
+
rb_raise(rb_eArgError, "Invalid value for increment %d", incr);
|
538
|
+
}
|
539
|
+
i_mm->t->incr = incr;
|
540
|
+
}
|
541
|
+
else if (strcmp(options, "initialize") == 0) {
|
542
|
+
}
|
543
|
+
#if HAVE_SEMCTL && HAVE_SHMCTL
|
544
|
+
else if (strcmp(options, "ipc") == 0) {
|
545
|
+
if (value != Qtrue && TYPE(value) != T_HASH) {
|
546
|
+
rb_raise(rb_eArgError, "Expected an Hash for :ipc");
|
547
|
+
}
|
548
|
+
i_mm->t->shmid = value;
|
549
|
+
i_mm->t->flag |= (MM_IPC | MM_TMP);
|
550
|
+
}
|
551
|
+
#endif
|
552
|
+
else {
|
553
|
+
rb_warning("Unknown option `%s'", options);
|
554
|
+
}
|
555
|
+
return Qnil;
|
556
|
+
}
|
557
|
+
|
558
|
+
#if HAVE_SEMCTL && HAVE_SHMCTL
|
559
|
+
|
560
|
+
static VALUE
|
561
|
+
mm_i_ipc(arg, obj)
|
562
|
+
VALUE arg, obj;
|
563
|
+
{
|
564
|
+
mm_ipc *i_mm;
|
565
|
+
char *options;
|
566
|
+
VALUE key, value;
|
567
|
+
|
568
|
+
Data_Get_Struct(obj, mm_ipc, i_mm);
|
569
|
+
key = rb_ary_entry(arg, 0);
|
570
|
+
value = rb_ary_entry(arg, 1);
|
571
|
+
key = rb_obj_as_string(key);
|
572
|
+
options = StringValuePtr(key);
|
573
|
+
if (strcmp(options, "key") == 0) {
|
574
|
+
i_mm->t->key = rb_funcall2(value, rb_intern("to_int"), 0, 0);
|
575
|
+
}
|
576
|
+
else if (strcmp(options, "permanent") == 0) {
|
577
|
+
if (RTEST(value)) {
|
578
|
+
i_mm->t->flag &= ~MM_TMP;
|
579
|
+
}
|
580
|
+
}
|
581
|
+
else if (strcmp(options, "mode") == 0) {
|
582
|
+
i_mm->t->semid = NUM2INT(value);
|
583
|
+
}
|
584
|
+
else {
|
585
|
+
rb_warning("Unknown option `%s'", options);
|
586
|
+
}
|
587
|
+
return Qnil;
|
588
|
+
}
|
589
|
+
|
590
|
+
#endif
|
591
|
+
|
592
|
+
/*
|
593
|
+
* call-seq:
|
594
|
+
* new(file, mode = "r", protection = Mmap::MAP_SHARED, options = {})
|
595
|
+
*
|
596
|
+
* create a new Mmap object
|
597
|
+
*
|
598
|
+
* * <em>file</em>
|
599
|
+
*
|
600
|
+
* Pathname of the file, if <em>nil</em> is given an anonymous map
|
601
|
+
* is created <em>Mmanp::MAP_ANON</em>
|
602
|
+
*
|
603
|
+
* * <em>mode</em>
|
604
|
+
*
|
605
|
+
* Mode to open the file, it can be "r", "w", "rw", "a"
|
606
|
+
*
|
607
|
+
* * <em>protection</em>
|
608
|
+
*
|
609
|
+
* specify the nature of the mapping
|
610
|
+
*
|
611
|
+
* * <em>Mmap::MAP_SHARED</em>
|
612
|
+
*
|
613
|
+
* Creates a mapping that's shared with all other processes
|
614
|
+
* mapping the same areas of the file.
|
615
|
+
* The default value is <em>Mmap::MAP_SHARED</em>
|
616
|
+
*
|
617
|
+
* * <em>Mmap::MAP_PRIVATE</em>
|
618
|
+
*
|
619
|
+
* Creates a private copy-on-write mapping, so changes to the
|
620
|
+
* contents of the mmap object will be private to this process
|
621
|
+
*
|
622
|
+
* * <em>options</em>
|
623
|
+
*
|
624
|
+
* Hash. If one of the options <em>length</em> or <em>offset</em>
|
625
|
+
* is specified it will not possible to modify the size of
|
626
|
+
* the mapped file.
|
627
|
+
*
|
628
|
+
* length:: maps <em>length</em> bytes from the file
|
629
|
+
*
|
630
|
+
* offset:: the mapping begin at <em>offset</em>
|
631
|
+
*
|
632
|
+
* advice:: the type of the access (see #madvise)
|
633
|
+
*/
|
634
|
+
static VALUE
|
635
|
+
mm_s_new(argc, argv, obj)
|
636
|
+
int argc;
|
637
|
+
VALUE *argv, obj;
|
638
|
+
{
|
639
|
+
VALUE res = rb_funcall2(obj, rb_intern("allocate"), 0, 0);
|
640
|
+
rb_obj_call_init(res, argc, argv);
|
641
|
+
return res;
|
642
|
+
}
|
643
|
+
|
644
|
+
static VALUE
|
645
|
+
mm_s_alloc(obj)
|
646
|
+
VALUE obj;
|
647
|
+
{
|
648
|
+
VALUE res;
|
649
|
+
mm_ipc *i_mm;
|
650
|
+
|
651
|
+
res = Data_Make_Struct(obj, mm_ipc, 0, mm_free, i_mm);
|
652
|
+
i_mm->t = ALLOC_N(mm_mmap, 1);
|
653
|
+
MEMZERO(i_mm->t, mm_mmap, 1);
|
654
|
+
i_mm->t->incr = EXP_INCR_SIZE;
|
655
|
+
return res;
|
656
|
+
}
|
657
|
+
|
658
|
+
/*
|
659
|
+
* call-seq: initialize
|
660
|
+
*
|
661
|
+
* Create a new Mmap object
|
662
|
+
*/
|
663
|
+
static VALUE
|
664
|
+
mm_init(argc, argv, obj)
|
665
|
+
VALUE obj, *argv;
|
666
|
+
int argc;
|
667
|
+
{
|
668
|
+
struct stat st;
|
669
|
+
int fd, smode = 0, pmode = 0, vscope, perm, init;
|
670
|
+
MMAP_RETTYPE addr;
|
671
|
+
VALUE fname, fdv, vmode, scope, options;
|
672
|
+
mm_ipc *i_mm;
|
673
|
+
char *path, *mode;
|
674
|
+
size_t size = 0;
|
675
|
+
off_t offset;
|
676
|
+
int anonymous;
|
677
|
+
|
678
|
+
options = Qnil;
|
679
|
+
if (argc > 1 && TYPE(argv[argc - 1]) == T_HASH) {
|
680
|
+
options = argv[argc - 1];
|
681
|
+
argc--;
|
682
|
+
}
|
683
|
+
rb_scan_args(argc, argv, "12", &fname, &vmode, &scope);
|
684
|
+
vscope = 0;
|
685
|
+
path = 0;
|
686
|
+
fd = -1;
|
687
|
+
anonymous = 0;
|
688
|
+
fdv = Qnil;
|
689
|
+
#ifdef MAP_ANON
|
690
|
+
if (NIL_P(fname)) {
|
691
|
+
vscope = MAP_ANON | MAP_SHARED;
|
692
|
+
anonymous = 1;
|
693
|
+
}
|
694
|
+
else
|
695
|
+
#endif
|
696
|
+
{
|
697
|
+
if (rb_safe_level() > 0 && OBJ_TAINTED(fname)){
|
698
|
+
rb_raise(rb_eSecurityError, "Insecure operation");
|
699
|
+
}
|
700
|
+
rb_secure(4);
|
701
|
+
if (rb_respond_to(fname, rb_intern("fileno"))) {
|
702
|
+
fdv = rb_funcall2(fname, rb_intern("fileno"), 0, 0);
|
703
|
+
}
|
704
|
+
if (NIL_P(fdv)) {
|
705
|
+
fname = rb_str_to_str(fname);
|
706
|
+
SafeStringValue(fname);
|
707
|
+
path = StringValuePtr(fname);
|
708
|
+
}
|
709
|
+
else {
|
710
|
+
fd = NUM2INT(fdv);
|
711
|
+
if (fd < 0) {
|
712
|
+
rb_raise(rb_eArgError, "invalid file descriptor %d", fd);
|
713
|
+
}
|
714
|
+
}
|
715
|
+
if (!NIL_P(scope)) {
|
716
|
+
vscope = NUM2INT(scope);
|
717
|
+
#ifdef MAP_ANON
|
718
|
+
if (vscope & MAP_ANON) {
|
719
|
+
rb_raise(rb_eArgError, "filename specified for an anonymous map");
|
720
|
+
}
|
721
|
+
#endif
|
722
|
+
}
|
723
|
+
}
|
724
|
+
vscope |= NIL_P(scope) ? MAP_SHARED : NUM2INT(scope);
|
725
|
+
size = 0;
|
726
|
+
perm = 0666;
|
727
|
+
if (!anonymous) {
|
728
|
+
if (NIL_P(vmode)) {
|
729
|
+
mode = "r";
|
730
|
+
}
|
731
|
+
else if (rb_respond_to(vmode, rb_intern("to_ary"))) {
|
732
|
+
VALUE tmp;
|
733
|
+
|
734
|
+
vmode = rb_convert_type(vmode, T_ARRAY, "Array", "to_ary");
|
735
|
+
if (RARRAY(vmode)->len != 2) {
|
736
|
+
rb_raise(rb_eArgError, "Invalid length %d (expected 2)",
|
737
|
+
RARRAY(vmode)->len);
|
738
|
+
}
|
739
|
+
tmp = RARRAY(vmode)->ptr[0];
|
740
|
+
mode = StringValuePtr(tmp);
|
741
|
+
perm = NUM2INT(RARRAY(vmode)->ptr[1]);
|
742
|
+
}
|
743
|
+
else {
|
744
|
+
mode = StringValuePtr(vmode);
|
745
|
+
}
|
746
|
+
if (strcmp(mode, "r") == 0) {
|
747
|
+
smode = O_RDONLY;
|
748
|
+
pmode = PROT_READ;
|
749
|
+
}
|
750
|
+
else if (strcmp(mode, "w") == 0) {
|
751
|
+
smode = O_RDWR | O_TRUNC;
|
752
|
+
pmode = PROT_READ | PROT_WRITE;
|
753
|
+
}
|
754
|
+
else if (strcmp(mode, "rw") == 0 || strcmp(mode, "wr") == 0) {
|
755
|
+
smode = O_RDWR;
|
756
|
+
pmode = PROT_READ | PROT_WRITE;
|
757
|
+
}
|
758
|
+
else if (strcmp(mode, "a") == 0) {
|
759
|
+
smode = O_RDWR | O_CREAT;
|
760
|
+
pmode = PROT_READ | PROT_WRITE;
|
761
|
+
}
|
762
|
+
else {
|
763
|
+
rb_raise(rb_eArgError, "Invalid mode %s", mode);
|
764
|
+
}
|
765
|
+
if (NIL_P(fdv)) {
|
766
|
+
if ((fd = open(path, smode, perm)) == -1) {
|
767
|
+
rb_raise(rb_eArgError, "Can't open %s", path);
|
768
|
+
}
|
769
|
+
}
|
770
|
+
if (fstat(fd, &st) == -1) {
|
771
|
+
rb_raise(rb_eArgError, "Can't stat %s", path);
|
772
|
+
}
|
773
|
+
size = st.st_size;
|
774
|
+
}
|
775
|
+
else {
|
776
|
+
fd = -1;
|
777
|
+
if (!NIL_P(vmode) && TYPE(vmode) != T_STRING) {
|
778
|
+
size = NUM2INT(vmode);
|
779
|
+
}
|
780
|
+
}
|
781
|
+
Data_Get_Struct(obj, mm_ipc, i_mm);
|
782
|
+
if (i_mm->t->flag & MM_FROZEN) {
|
783
|
+
rb_raise(rb_eArgError, "frozen mmap");
|
784
|
+
}
|
785
|
+
i_mm->t->shmid = 0;
|
786
|
+
i_mm->t->semid = 0;
|
787
|
+
offset = 0;
|
788
|
+
if (options != Qnil) {
|
789
|
+
rb_iterate(rb_each, options, mm_i_options, obj);
|
790
|
+
if (path && (i_mm->t->len + i_mm->t->offset) > st.st_size) {
|
791
|
+
rb_raise(rb_eArgError, "invalid value for length (%d) or offset (%d)",
|
792
|
+
i_mm->t->len, i_mm->t->offset);
|
793
|
+
}
|
794
|
+
if (i_mm->t->len) size = i_mm->t->len;
|
795
|
+
offset = i_mm->t->offset;
|
796
|
+
#if HAVE_SEMCTL && HAVE_SHMCTL
|
797
|
+
if (i_mm->t->flag & MM_IPC) {
|
798
|
+
key_t key;
|
799
|
+
int shmid, semid, mode;
|
800
|
+
union semun sem_val;
|
801
|
+
struct shmid_ds buf;
|
802
|
+
mm_mmap *data;
|
803
|
+
|
804
|
+
if (!(vscope & MAP_SHARED)) {
|
805
|
+
rb_warning("Probably it will not do what you expect ...");
|
806
|
+
}
|
807
|
+
i_mm->t->key = -1;
|
808
|
+
i_mm->t->semid = 0;
|
809
|
+
if (TYPE(i_mm->t->shmid) == T_HASH) {
|
810
|
+
rb_iterate(rb_each, i_mm->t->shmid, mm_i_ipc, obj);
|
811
|
+
}
|
812
|
+
i_mm->t->shmid = 0;
|
813
|
+
if (i_mm->t->semid) {
|
814
|
+
mode = i_mm->t->semid;
|
815
|
+
i_mm->t->semid = 0;
|
816
|
+
}
|
817
|
+
else {
|
818
|
+
mode = 0644;
|
819
|
+
}
|
820
|
+
if ((int)i_mm->t->key <= 0) {
|
821
|
+
mode |= IPC_CREAT;
|
822
|
+
strcpy(template, "/tmp/ruby_mmap.XXXXXX");
|
823
|
+
if (mkstemp(template) == -1) {
|
824
|
+
rb_sys_fail("mkstemp()");
|
825
|
+
}
|
826
|
+
if ((key = ftok(template, 'R')) == -1) {
|
827
|
+
rb_sys_fail("ftok()");
|
828
|
+
}
|
829
|
+
}
|
830
|
+
else {
|
831
|
+
key = (key_t)i_mm->t->key;
|
832
|
+
}
|
833
|
+
if ((shmid = shmget(key, sizeof(mm_ipc), mode)) == -1) {
|
834
|
+
rb_sys_fail("shmget()");
|
835
|
+
}
|
836
|
+
data = shmat(shmid, (void *)0, 0);
|
837
|
+
if (data == (mm_mmap *)-1) {
|
838
|
+
rb_sys_fail("shmat()");
|
839
|
+
}
|
840
|
+
if (i_mm->t->flag & MM_TMP) {
|
841
|
+
if (shmctl(shmid, IPC_RMID, &buf) == -1) {
|
842
|
+
rb_sys_fail("shmctl()");
|
843
|
+
}
|
844
|
+
}
|
845
|
+
if ((semid = semget(key, 1, mode)) == -1) {
|
846
|
+
rb_sys_fail("semget()");
|
847
|
+
}
|
848
|
+
if (mode & IPC_CREAT) {
|
849
|
+
sem_val.val = 1;
|
850
|
+
if (semctl(semid, 0, SETVAL, sem_val) == -1) {
|
851
|
+
rb_sys_fail("semctl()");
|
852
|
+
}
|
853
|
+
}
|
854
|
+
memcpy(data, i_mm->t, sizeof(mm_mmap));
|
855
|
+
free(i_mm->t);
|
856
|
+
i_mm->t = data;
|
857
|
+
i_mm->t->key = key;
|
858
|
+
i_mm->t->semid = semid;
|
859
|
+
i_mm->t->shmid = shmid;
|
860
|
+
if (i_mm->t->flag & MM_TMP) {
|
861
|
+
i_mm->t->template = ALLOC_N(char, strlen(template) + 1);
|
862
|
+
strcpy(i_mm->t->template, template);
|
863
|
+
}
|
864
|
+
}
|
865
|
+
#endif
|
866
|
+
}
|
867
|
+
init = 0;
|
868
|
+
if (anonymous) {
|
869
|
+
if (size <= 0) {
|
870
|
+
rb_raise(rb_eArgError, "length not specified for an anonymous map");
|
871
|
+
}
|
872
|
+
if (offset) {
|
873
|
+
rb_warning("Ignoring offset for an anonymous map");
|
874
|
+
offset = 0;
|
875
|
+
}
|
876
|
+
smode = O_RDWR;
|
877
|
+
pmode = PROT_READ | PROT_WRITE;
|
878
|
+
i_mm->t->flag |= MM_FIXED | MM_ANON;
|
879
|
+
}
|
880
|
+
else {
|
881
|
+
if (size == 0 && (smode & O_RDWR)) {
|
882
|
+
if (lseek(fd, i_mm->t->incr - 1, SEEK_END) == -1) {
|
883
|
+
rb_raise(rb_eIOError, "Can't lseek %d", i_mm->t->incr - 1);
|
884
|
+
}
|
885
|
+
if (write(fd, "\000", 1) != 1) {
|
886
|
+
rb_raise(rb_eIOError, "Can't extend %s", path);
|
887
|
+
}
|
888
|
+
init = 1;
|
889
|
+
size = i_mm->t->incr;
|
890
|
+
}
|
891
|
+
if (!NIL_P(fdv)) {
|
892
|
+
i_mm->t->flag |= MM_FIXED;
|
893
|
+
}
|
894
|
+
}
|
895
|
+
addr = mmap(0, size, pmode, vscope, fd, offset);
|
896
|
+
if (NIL_P(fdv) && !anonymous) {
|
897
|
+
close(fd);
|
898
|
+
}
|
899
|
+
if (addr == MAP_FAILED || !addr) {
|
900
|
+
rb_raise(rb_eArgError, "mmap failed (%d)", errno);
|
901
|
+
}
|
902
|
+
#ifdef MADV_NORMAL
|
903
|
+
if (i_mm->t->advice && madvise(addr, size, i_mm->t->advice) == -1) {
|
904
|
+
rb_raise(rb_eArgError, "madvise(%d)", errno);
|
905
|
+
}
|
906
|
+
#endif
|
907
|
+
if (anonymous && TYPE(options) == T_HASH) {
|
908
|
+
VALUE val;
|
909
|
+
char *ptr;
|
910
|
+
|
911
|
+
val = rb_hash_aref(options, rb_str_new2("initialize"));
|
912
|
+
if (!NIL_P(val)) {
|
913
|
+
ptr = StringValuePtr(val);
|
914
|
+
memset(addr, ptr[0], size);
|
915
|
+
}
|
916
|
+
}
|
917
|
+
i_mm->t->addr = addr;
|
918
|
+
i_mm->t->len = size;
|
919
|
+
if (!init) i_mm->t->real = size;
|
920
|
+
i_mm->t->pmode = pmode;
|
921
|
+
i_mm->t->vscope = vscope;
|
922
|
+
i_mm->t->smode = smode & ~O_TRUNC;
|
923
|
+
i_mm->t->path = (path)?ruby_strdup(path):(char *)-1;
|
924
|
+
if (smode == O_RDONLY) {
|
925
|
+
obj = rb_obj_freeze(obj);
|
926
|
+
i_mm->t->flag |= MM_FROZEN;
|
927
|
+
}
|
928
|
+
else {
|
929
|
+
if (smode == O_WRONLY) {
|
930
|
+
i_mm->t->flag |= MM_FIXED;
|
931
|
+
}
|
932
|
+
OBJ_TAINT(obj);
|
933
|
+
}
|
934
|
+
return obj;
|
935
|
+
}
|
936
|
+
|
937
|
+
/*
|
938
|
+
* Document-method: msync
|
939
|
+
* Document-method: sync
|
940
|
+
* Document-method: flush
|
941
|
+
*
|
942
|
+
* call-seq: msync
|
943
|
+
*
|
944
|
+
* flush the file
|
945
|
+
*/
|
946
|
+
static VALUE
|
947
|
+
mm_msync(argc, argv, obj)
|
948
|
+
int argc;
|
949
|
+
VALUE *argv, obj;
|
950
|
+
{
|
951
|
+
mm_ipc *i_mm;
|
952
|
+
VALUE oflag;
|
953
|
+
int ret;
|
954
|
+
int flag = MS_SYNC;
|
955
|
+
|
956
|
+
if (argc) {
|
957
|
+
rb_scan_args(argc, argv, "01", &oflag);
|
958
|
+
flag = NUM2INT(oflag);
|
959
|
+
}
|
960
|
+
GetMmap(obj, i_mm, MM_MODIFY);
|
961
|
+
if ((ret = msync(i_mm->t->addr, i_mm->t->len, flag)) != 0) {
|
962
|
+
rb_raise(rb_eArgError, "msync(%d)", ret);
|
963
|
+
}
|
964
|
+
if (i_mm->t->real < i_mm->t->len && i_mm->t->vscope != MAP_PRIVATE)
|
965
|
+
mm_expandf(i_mm, i_mm->t->real);
|
966
|
+
return obj;
|
967
|
+
}
|
968
|
+
|
969
|
+
/*
|
970
|
+
* Document-method: mprotect
|
971
|
+
* Document-method: protect
|
972
|
+
*
|
973
|
+
* call-seq: mprotect(mode)
|
974
|
+
*
|
975
|
+
* change the mode, value must be "r", "w" or "rw"
|
976
|
+
*/
|
977
|
+
static VALUE
|
978
|
+
mm_mprotect(obj, a)
|
979
|
+
VALUE obj, a;
|
980
|
+
{
|
981
|
+
mm_ipc *i_mm;
|
982
|
+
int ret, pmode;
|
983
|
+
char *smode;
|
984
|
+
|
985
|
+
GetMmap(obj, i_mm, 0);
|
986
|
+
if (TYPE(a) == T_STRING) {
|
987
|
+
smode = StringValuePtr(a);
|
988
|
+
if (strcmp(smode, "r") == 0) pmode = PROT_READ;
|
989
|
+
else if (strcmp(smode, "w") == 0) pmode = PROT_WRITE;
|
990
|
+
else if (strcmp(smode, "rw") == 0 || strcmp(smode, "wr") == 0)
|
991
|
+
pmode = PROT_READ | PROT_WRITE;
|
992
|
+
else {
|
993
|
+
rb_raise(rb_eArgError, "Invalid mode %s", smode);
|
994
|
+
}
|
995
|
+
}
|
996
|
+
else {
|
997
|
+
pmode = NUM2INT(a);
|
998
|
+
}
|
999
|
+
if ((pmode & PROT_WRITE) && (i_mm->t->flag & MM_FROZEN))
|
1000
|
+
rb_error_frozen("mmap");
|
1001
|
+
if ((ret = mprotect(i_mm->t->addr, i_mm->t->len, pmode | PROT_READ)) != 0) {
|
1002
|
+
rb_raise(rb_eArgError, "mprotect(%d)", ret);
|
1003
|
+
}
|
1004
|
+
i_mm->t->pmode = pmode;
|
1005
|
+
if (pmode & PROT_READ) {
|
1006
|
+
if (pmode & PROT_WRITE) i_mm->t->smode = O_RDWR;
|
1007
|
+
else {
|
1008
|
+
i_mm->t->smode = O_RDONLY;
|
1009
|
+
obj = rb_obj_freeze(obj);
|
1010
|
+
i_mm->t->flag |= MM_FROZEN;
|
1011
|
+
}
|
1012
|
+
}
|
1013
|
+
else if (pmode & PROT_WRITE) {
|
1014
|
+
i_mm->t->flag |= MM_FIXED;
|
1015
|
+
i_mm->t->smode = O_WRONLY;
|
1016
|
+
}
|
1017
|
+
return obj;
|
1018
|
+
}
|
1019
|
+
|
1020
|
+
#ifdef MADV_NORMAL
|
1021
|
+
/*
|
1022
|
+
* Document-method: madvise
|
1023
|
+
* Document-method: advise
|
1024
|
+
*
|
1025
|
+
* call-seq: madvise(advice)
|
1026
|
+
*
|
1027
|
+
* <em>advice</em> can have the value <em>Mmap::MADV_NORMAL</em>,
|
1028
|
+
* <em>Mmap::MADV_RANDOM</em>, <em>Mmap::MADV_SEQUENTIAL</em>,
|
1029
|
+
* <em>Mmap::MADV_WILLNEED</em>, <em>Mmap::MADV_DONTNEED</em>
|
1030
|
+
*
|
1031
|
+
*/
|
1032
|
+
static VALUE
|
1033
|
+
mm_madvise(obj, a)
|
1034
|
+
VALUE obj, a;
|
1035
|
+
{
|
1036
|
+
mm_ipc *i_mm;
|
1037
|
+
|
1038
|
+
GetMmap(obj, i_mm, 0);
|
1039
|
+
if (madvise(i_mm->t->addr, i_mm->t->len, NUM2INT(a)) == -1) {
|
1040
|
+
rb_raise(rb_eTypeError, "madvise(%d)", errno);
|
1041
|
+
}
|
1042
|
+
i_mm->t->advice = NUM2INT(a);
|
1043
|
+
return Qnil;
|
1044
|
+
}
|
1045
|
+
#endif
|
1046
|
+
|
1047
|
+
#define StringMmap(b, bp, bl) \
|
1048
|
+
do { \
|
1049
|
+
if (TYPE(b) == T_DATA && RDATA(b)->dfree == (RUBY_DATA_FUNC)mm_free) { \
|
1050
|
+
mm_ipc *b_mm; \
|
1051
|
+
GetMmap(b, b_mm, 0); \
|
1052
|
+
bp = b_mm->t->addr; \
|
1053
|
+
bl = b_mm->t->real; \
|
1054
|
+
} \
|
1055
|
+
else { \
|
1056
|
+
bp = StringValuePtr(b); \
|
1057
|
+
bl = RSTRING(b)->len; \
|
1058
|
+
} \
|
1059
|
+
} while (0);
|
1060
|
+
|
1061
|
+
static void
|
1062
|
+
mm_update(str, beg, len, val)
|
1063
|
+
mm_ipc *str;
|
1064
|
+
VALUE val;
|
1065
|
+
long beg;
|
1066
|
+
long len;
|
1067
|
+
{
|
1068
|
+
char *valp;
|
1069
|
+
long vall;
|
1070
|
+
|
1071
|
+
if (str->t->flag & MM_FROZEN) rb_error_frozen("mmap");
|
1072
|
+
if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len);
|
1073
|
+
mm_lock(str);
|
1074
|
+
if (beg < 0) {
|
1075
|
+
beg += str->t->real;
|
1076
|
+
}
|
1077
|
+
if (beg < 0 || str->t->real < (size_t)beg) {
|
1078
|
+
if (beg < 0) {
|
1079
|
+
beg -= str->t->real;
|
1080
|
+
}
|
1081
|
+
mm_unlock(str);
|
1082
|
+
rb_raise(rb_eIndexError, "index %d out of string", beg);
|
1083
|
+
}
|
1084
|
+
if (str->t->real < (size_t)(beg + len)) {
|
1085
|
+
len = str->t->real - beg;
|
1086
|
+
}
|
1087
|
+
|
1088
|
+
mm_unlock(str);
|
1089
|
+
StringMmap(val, valp, vall);
|
1090
|
+
mm_lock(str);
|
1091
|
+
|
1092
|
+
if ((str->t->flag & MM_FIXED) && vall != len) {
|
1093
|
+
mm_unlock(str);
|
1094
|
+
rb_raise(rb_eTypeError, "try to change the size of a fixed map");
|
1095
|
+
}
|
1096
|
+
if (len < vall) {
|
1097
|
+
mm_realloc(str, str->t->real + vall - len);
|
1098
|
+
}
|
1099
|
+
|
1100
|
+
if (vall != len) {
|
1101
|
+
memmove((char *)str->t->addr + beg + vall,
|
1102
|
+
(char *)str->t->addr + beg + len,
|
1103
|
+
str->t->real - (beg + len));
|
1104
|
+
}
|
1105
|
+
if (str->t->real < (size_t)beg && len < 0) {
|
1106
|
+
MEMZERO(str->t->addr + str->t->real, char, -len);
|
1107
|
+
}
|
1108
|
+
if (vall > 0) {
|
1109
|
+
memmove((char *)str->t->addr + beg, valp, vall);
|
1110
|
+
}
|
1111
|
+
str->t->real += vall - len;
|
1112
|
+
mm_unlock(str);
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
/*
|
1116
|
+
* call-seq: =~(other)
|
1117
|
+
*
|
1118
|
+
* return an index of the match
|
1119
|
+
*/
|
1120
|
+
static VALUE
|
1121
|
+
mm_match(x, y)
|
1122
|
+
VALUE x, y;
|
1123
|
+
{
|
1124
|
+
VALUE reg, res;
|
1125
|
+
long start;
|
1126
|
+
|
1127
|
+
x = mm_str(x, MM_ORIGIN);
|
1128
|
+
if (TYPE(y) == T_DATA && RDATA(y)->dfree == (RUBY_DATA_FUNC)mm_free) {
|
1129
|
+
y = mm_to_str(y);
|
1130
|
+
}
|
1131
|
+
switch (TYPE(y)) {
|
1132
|
+
case T_REGEXP:
|
1133
|
+
res = rb_reg_match(y, x);
|
1134
|
+
break;
|
1135
|
+
|
1136
|
+
case T_STRING:
|
1137
|
+
reg = rb_reg_regcomp(y);
|
1138
|
+
start = rb_reg_search(reg, x, 0, 0);
|
1139
|
+
if (start == -1) res = Qnil;
|
1140
|
+
else res = INT2NUM(start);
|
1141
|
+
break;
|
1142
|
+
|
1143
|
+
default:
|
1144
|
+
res = rb_funcall(y, rb_intern("=~"), 1, x);
|
1145
|
+
break;
|
1146
|
+
}
|
1147
|
+
return res;
|
1148
|
+
}
|
1149
|
+
|
1150
|
+
static VALUE
|
1151
|
+
get_pat(pat)
|
1152
|
+
VALUE pat;
|
1153
|
+
{
|
1154
|
+
switch (TYPE(pat)) {
|
1155
|
+
case T_REGEXP:
|
1156
|
+
break;
|
1157
|
+
|
1158
|
+
case T_STRING:
|
1159
|
+
pat = rb_reg_regcomp(pat);
|
1160
|
+
break;
|
1161
|
+
|
1162
|
+
default:
|
1163
|
+
/* type failed */
|
1164
|
+
Check_Type(pat, T_REGEXP);
|
1165
|
+
}
|
1166
|
+
return pat;
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
static int
|
1170
|
+
mm_correct_backref()
|
1171
|
+
{
|
1172
|
+
VALUE match;
|
1173
|
+
int i, start;
|
1174
|
+
|
1175
|
+
match = rb_backref_get();
|
1176
|
+
if (NIL_P(match)) return 0;
|
1177
|
+
if (RMATCH(match)->BEG(0) == -1) return 0;
|
1178
|
+
start = RMATCH(match)->BEG(0);
|
1179
|
+
RMATCH(match)->str = rb_str_new(StringValuePtr(RMATCH(match)->str) + start,
|
1180
|
+
RMATCH(match)->END(0) - start);
|
1181
|
+
if (OBJ_TAINTED(match)) OBJ_TAINT(RMATCH(match)->str);
|
1182
|
+
for (i = 0; i < RMATCH(match)->regs->num_regs && RMATCH(match)->BEG(i) != -1; i++) {
|
1183
|
+
RMATCH(match)->BEG(i) -= start;
|
1184
|
+
RMATCH(match)->END(i) -= start;
|
1185
|
+
}
|
1186
|
+
rb_backref_set(match);
|
1187
|
+
return start;
|
1188
|
+
}
|
1189
|
+
|
1190
|
+
static VALUE
|
1191
|
+
mm_sub_bang_int(bang_st)
|
1192
|
+
mm_bang *bang_st;
|
1193
|
+
{
|
1194
|
+
int argc = bang_st->argc;
|
1195
|
+
VALUE *argv = bang_st->argv;
|
1196
|
+
VALUE obj = bang_st->obj;
|
1197
|
+
VALUE pat, repl = Qnil, match, str, res;
|
1198
|
+
struct re_registers *regs;
|
1199
|
+
int start, iter = 0;
|
1200
|
+
int tainted = 0;
|
1201
|
+
long plen;
|
1202
|
+
mm_ipc *i_mm;
|
1203
|
+
|
1204
|
+
if (argc == 1 && rb_block_given_p()) {
|
1205
|
+
iter = 1;
|
1206
|
+
}
|
1207
|
+
else if (argc == 2) {
|
1208
|
+
repl = rb_str_to_str(argv[1]);
|
1209
|
+
if (OBJ_TAINTED(repl)) tainted = 1;
|
1210
|
+
}
|
1211
|
+
else {
|
1212
|
+
rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc);
|
1213
|
+
}
|
1214
|
+
GetMmap(obj, i_mm, MM_MODIFY);
|
1215
|
+
str = mm_str(obj, MM_MODIFY | MM_ORIGIN);
|
1216
|
+
|
1217
|
+
pat = get_pat(argv[0]);
|
1218
|
+
res = Qnil;
|
1219
|
+
if (rb_reg_search(pat, str, 0, 0) >= 0) {
|
1220
|
+
start = mm_correct_backref();
|
1221
|
+
match = rb_backref_get();
|
1222
|
+
regs = RMATCH(match)->regs;
|
1223
|
+
if (iter) {
|
1224
|
+
rb_match_busy(match);
|
1225
|
+
repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
|
1226
|
+
rb_backref_set(match);
|
1227
|
+
}
|
1228
|
+
else {
|
1229
|
+
RSTRING(str)->ptr += start;
|
1230
|
+
repl = rb_reg_regsub(repl, str, regs);
|
1231
|
+
RSTRING(str)->ptr -= start;
|
1232
|
+
}
|
1233
|
+
if (OBJ_TAINTED(repl)) tainted = 1;
|
1234
|
+
plen = END(0) - BEG(0);
|
1235
|
+
if (RSTRING(repl)->len > plen) {
|
1236
|
+
mm_realloc(i_mm, RSTRING(str)->len + RSTRING(repl)->len - plen);
|
1237
|
+
RSTRING(str)->ptr = i_mm->t->addr;
|
1238
|
+
}
|
1239
|
+
if (RSTRING(repl)->len != plen) {
|
1240
|
+
if (i_mm->t->flag & MM_FIXED) {
|
1241
|
+
rb_raise(rb_eTypeError, "try to change the size of a fixed map");
|
1242
|
+
}
|
1243
|
+
memmove(RSTRING(str)->ptr + start + BEG(0) + RSTRING(repl)->len,
|
1244
|
+
RSTRING(str)->ptr + start + BEG(0) + plen,
|
1245
|
+
RSTRING(str)->len - start - BEG(0) - plen);
|
1246
|
+
}
|
1247
|
+
memcpy(RSTRING(str)->ptr + start + BEG(0),
|
1248
|
+
RSTRING(repl)->ptr, RSTRING(repl)->len);
|
1249
|
+
i_mm->t->real += RSTRING(repl)->len - plen;
|
1250
|
+
if (tainted) OBJ_TAINT(obj);
|
1251
|
+
|
1252
|
+
res = obj;
|
1253
|
+
}
|
1254
|
+
rb_gc_force_recycle(str);
|
1255
|
+
return res;
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
/*
|
1259
|
+
* call-seq:
|
1260
|
+
* str.sub!(pattern, replacement) => str or nil
|
1261
|
+
* str.sub!(pattern) {|match| block } => str or nil
|
1262
|
+
*
|
1263
|
+
* substitution
|
1264
|
+
*/
|
1265
|
+
static VALUE
|
1266
|
+
mm_sub_bang(argc, argv, obj)
|
1267
|
+
int argc;
|
1268
|
+
VALUE *argv;
|
1269
|
+
VALUE obj;
|
1270
|
+
{
|
1271
|
+
VALUE res;
|
1272
|
+
mm_bang bang_st;
|
1273
|
+
mm_ipc *i_mm;
|
1274
|
+
|
1275
|
+
bang_st.argc = argc;
|
1276
|
+
bang_st.argv = argv;
|
1277
|
+
bang_st.obj = obj;
|
1278
|
+
GetMmap(obj, i_mm, MM_MODIFY);
|
1279
|
+
if (i_mm->t->flag & MM_IPC) {
|
1280
|
+
mm_lock(i_mm, Qtrue);
|
1281
|
+
res = rb_ensure(mm_sub_bang_int, (VALUE)&bang_st, mm_vunlock, obj);
|
1282
|
+
}
|
1283
|
+
else {
|
1284
|
+
res = mm_sub_bang_int(&bang_st);
|
1285
|
+
}
|
1286
|
+
return res;
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
static VALUE
|
1290
|
+
mm_gsub_bang_int(bang_st)
|
1291
|
+
mm_bang *bang_st;
|
1292
|
+
{
|
1293
|
+
int argc = bang_st->argc;
|
1294
|
+
VALUE *argv = bang_st->argv;
|
1295
|
+
VALUE obj = bang_st->obj;
|
1296
|
+
VALUE pat, val, repl = Qnil, match, str;
|
1297
|
+
struct re_registers *regs;
|
1298
|
+
long beg, offset;
|
1299
|
+
int start, iter = 0;
|
1300
|
+
int tainted = 0;
|
1301
|
+
long plen;
|
1302
|
+
mm_ipc *i_mm;
|
1303
|
+
|
1304
|
+
if (argc == 1 && rb_block_given_p()) {
|
1305
|
+
iter = 1;
|
1306
|
+
}
|
1307
|
+
else if (argc == 2) {
|
1308
|
+
repl = rb_str_to_str(argv[1]);
|
1309
|
+
if (OBJ_TAINTED(repl)) tainted = 1;
|
1310
|
+
}
|
1311
|
+
else {
|
1312
|
+
rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc);
|
1313
|
+
}
|
1314
|
+
GetMmap(obj, i_mm, MM_MODIFY);
|
1315
|
+
str = mm_str(obj, MM_MODIFY | MM_ORIGIN);
|
1316
|
+
|
1317
|
+
pat = get_pat(argv[0]);
|
1318
|
+
offset = 0;
|
1319
|
+
beg = rb_reg_search(pat, str, 0, 0);
|
1320
|
+
if (beg < 0) {
|
1321
|
+
rb_gc_force_recycle(str);
|
1322
|
+
return Qnil;
|
1323
|
+
}
|
1324
|
+
while (beg >= 0) {
|
1325
|
+
start = mm_correct_backref();
|
1326
|
+
match = rb_backref_get();
|
1327
|
+
regs = RMATCH(match)->regs;
|
1328
|
+
if (iter) {
|
1329
|
+
rb_match_busy(match);
|
1330
|
+
val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
|
1331
|
+
rb_backref_set(match);
|
1332
|
+
}
|
1333
|
+
else {
|
1334
|
+
RSTRING(str)->ptr += start;
|
1335
|
+
val = rb_reg_regsub(repl, str, regs);
|
1336
|
+
RSTRING(str)->ptr -= start;
|
1337
|
+
}
|
1338
|
+
if (OBJ_TAINTED(repl)) tainted = 1;
|
1339
|
+
plen = END(0) - BEG(0);
|
1340
|
+
if ((i_mm->t->real + RSTRING(val)->len - plen) > i_mm->t->len) {
|
1341
|
+
mm_realloc(i_mm, RSTRING(str)->len + RSTRING(val)->len - plen);
|
1342
|
+
}
|
1343
|
+
if (RSTRING(val)->len != plen) {
|
1344
|
+
if (i_mm->t->flag & MM_FIXED) {
|
1345
|
+
rb_raise(rb_eTypeError, "try to change the size of a fixed map");
|
1346
|
+
}
|
1347
|
+
memmove(RSTRING(str)->ptr + start + BEG(0) + RSTRING(val)->len,
|
1348
|
+
RSTRING(str)->ptr + start + BEG(0) + plen,
|
1349
|
+
RSTRING(str)->len - start - BEG(0) - plen);
|
1350
|
+
}
|
1351
|
+
memcpy(RSTRING(str)->ptr + start + BEG(0),
|
1352
|
+
RSTRING(val)->ptr, RSTRING(val)->len);
|
1353
|
+
RSTRING(str)->len += RSTRING(val)->len - plen;
|
1354
|
+
i_mm->t->real = RSTRING(str)->len;
|
1355
|
+
if (BEG(0) == END(0)) {
|
1356
|
+
offset = start + END(0) + mbclen2(RSTRING(str)->ptr[END(0)], pat);
|
1357
|
+
offset += RSTRING(val)->len - plen;
|
1358
|
+
}
|
1359
|
+
else {
|
1360
|
+
offset = start + END(0) + RSTRING(val)->len - plen;
|
1361
|
+
}
|
1362
|
+
if (offset > RSTRING(str)->len) break;
|
1363
|
+
beg = rb_reg_search(pat, str, offset, 0);
|
1364
|
+
}
|
1365
|
+
rb_backref_set(match);
|
1366
|
+
if (tainted) OBJ_TAINT(obj);
|
1367
|
+
rb_gc_force_recycle(str);
|
1368
|
+
return obj;
|
1369
|
+
}
|
1370
|
+
|
1371
|
+
/*
|
1372
|
+
* call-seq:
|
1373
|
+
* str.gsub!(pattern, replacement) => str or nil
|
1374
|
+
* str.gsub!(pattern) {|match| block } => str or nil
|
1375
|
+
*
|
1376
|
+
* global substitution
|
1377
|
+
*/
|
1378
|
+
static VALUE
|
1379
|
+
mm_gsub_bang(argc, argv, obj)
|
1380
|
+
int argc;
|
1381
|
+
VALUE *argv;
|
1382
|
+
VALUE obj;
|
1383
|
+
{
|
1384
|
+
VALUE res;
|
1385
|
+
mm_bang bang_st;
|
1386
|
+
mm_ipc *i_mm;
|
1387
|
+
|
1388
|
+
bang_st.argc = argc;
|
1389
|
+
bang_st.argv = argv;
|
1390
|
+
bang_st.obj = obj;
|
1391
|
+
GetMmap(obj, i_mm, MM_MODIFY);
|
1392
|
+
if (i_mm->t->flag & MM_IPC) {
|
1393
|
+
mm_lock(i_mm, Qtrue);
|
1394
|
+
res = rb_ensure(mm_gsub_bang_int, (VALUE)&bang_st, mm_vunlock, obj);
|
1395
|
+
}
|
1396
|
+
else {
|
1397
|
+
res = mm_gsub_bang_int(&bang_st);
|
1398
|
+
}
|
1399
|
+
return res;
|
1400
|
+
}
|
1401
|
+
|
1402
|
+
static VALUE mm_index __((int, VALUE *, VALUE));
|
1403
|
+
|
1404
|
+
#if HAVE_RB_DEFINE_ALLOC_FUNC
|
1405
|
+
|
1406
|
+
static void
|
1407
|
+
mm_subpat_set(obj, re, offset, val)
|
1408
|
+
VALUE obj, re;
|
1409
|
+
int offset;
|
1410
|
+
VALUE val;
|
1411
|
+
{
|
1412
|
+
VALUE str, match;
|
1413
|
+
int start, end, len;
|
1414
|
+
mm_ipc *i_mm;
|
1415
|
+
|
1416
|
+
str = mm_str(obj, MM_MODIFY | MM_ORIGIN);
|
1417
|
+
if (rb_reg_search(re, str, 0, 0) < 0) {
|
1418
|
+
rb_raise(rb_eIndexError, "regexp not matched");
|
1419
|
+
}
|
1420
|
+
match = rb_backref_get();
|
1421
|
+
if (offset >= RMATCH(match)->regs->num_regs) {
|
1422
|
+
rb_raise(rb_eIndexError, "index %d out of regexp", offset);
|
1423
|
+
}
|
1424
|
+
|
1425
|
+
start = RMATCH(match)->BEG(offset);
|
1426
|
+
if (start == -1) {
|
1427
|
+
rb_raise(rb_eIndexError, "regexp group %d not matched", offset);
|
1428
|
+
}
|
1429
|
+
end = RMATCH(match)->END(offset);
|
1430
|
+
len = end - start;
|
1431
|
+
GetMmap(obj, i_mm, MM_MODIFY);
|
1432
|
+
mm_update(i_mm, start, len, val);
|
1433
|
+
}
|
1434
|
+
|
1435
|
+
#endif
|
1436
|
+
|
1437
|
+
static VALUE
|
1438
|
+
mm_aset(str, indx, val)
|
1439
|
+
VALUE str;
|
1440
|
+
VALUE indx, val;
|
1441
|
+
{
|
1442
|
+
long idx;
|
1443
|
+
mm_ipc *i_mm;
|
1444
|
+
|
1445
|
+
GetMmap(str, i_mm, MM_MODIFY);
|
1446
|
+
switch (TYPE(indx)) {
|
1447
|
+
case T_FIXNUM:
|
1448
|
+
num_index:
|
1449
|
+
idx = NUM2INT(indx);
|
1450
|
+
if (idx < 0) {
|
1451
|
+
idx += i_mm->t->real;
|
1452
|
+
}
|
1453
|
+
if (idx < 0 || i_mm->t->real <= (size_t)idx) {
|
1454
|
+
rb_raise(rb_eIndexError, "index %d out of string", idx);
|
1455
|
+
}
|
1456
|
+
if (FIXNUM_P(val)) {
|
1457
|
+
if (i_mm->t->real == (size_t)idx) {
|
1458
|
+
i_mm->t->real += 1;
|
1459
|
+
mm_realloc(i_mm, i_mm->t->real);
|
1460
|
+
}
|
1461
|
+
((char *)i_mm->t->addr)[idx] = NUM2INT(val) & 0xff;
|
1462
|
+
}
|
1463
|
+
else {
|
1464
|
+
mm_update(i_mm, idx, 1, val);
|
1465
|
+
}
|
1466
|
+
return val;
|
1467
|
+
|
1468
|
+
case T_REGEXP:
|
1469
|
+
#if HAVE_RB_DEFINE_ALLOC_FUNC
|
1470
|
+
mm_subpat_set(str, indx, 0, val);
|
1471
|
+
#else
|
1472
|
+
{
|
1473
|
+
VALUE args[2];
|
1474
|
+
args[0] = indx;
|
1475
|
+
args[1] = val;
|
1476
|
+
mm_sub_bang(2, args, str);
|
1477
|
+
}
|
1478
|
+
#endif
|
1479
|
+
return val;
|
1480
|
+
|
1481
|
+
case T_STRING:
|
1482
|
+
{
|
1483
|
+
VALUE res;
|
1484
|
+
|
1485
|
+
res = mm_index(1, &indx, str);
|
1486
|
+
if (!NIL_P(res)) {
|
1487
|
+
mm_update(i_mm, NUM2LONG(res), RSTRING(indx)->len, val);
|
1488
|
+
}
|
1489
|
+
return val;
|
1490
|
+
}
|
1491
|
+
|
1492
|
+
default:
|
1493
|
+
/* check if indx is Range */
|
1494
|
+
{
|
1495
|
+
long beg, len;
|
1496
|
+
if (rb_range_beg_len(indx, &beg, &len, i_mm->t->real, 2)) {
|
1497
|
+
mm_update(i_mm, beg, len, val);
|
1498
|
+
return val;
|
1499
|
+
}
|
1500
|
+
}
|
1501
|
+
idx = NUM2LONG(indx);
|
1502
|
+
goto num_index;
|
1503
|
+
}
|
1504
|
+
}
|
1505
|
+
|
1506
|
+
/*
|
1507
|
+
* call-seq: []=(args)
|
1508
|
+
*
|
1509
|
+
* Element assignement - with the following syntax
|
1510
|
+
*
|
1511
|
+
* self[nth] = val
|
1512
|
+
*
|
1513
|
+
* change the <em>nth</em> character with <em>val</em>
|
1514
|
+
*
|
1515
|
+
* self[start..last] = val
|
1516
|
+
*
|
1517
|
+
* change substring from <em>start</em> to <em>last</em> with <em>val</em>
|
1518
|
+
*
|
1519
|
+
* self[start, len] = val
|
1520
|
+
*
|
1521
|
+
* replace <em>length</em> characters from <em>start</em> with <em>val</em>.
|
1522
|
+
*
|
1523
|
+
*/
|
1524
|
+
static VALUE
|
1525
|
+
mm_aset_m(argc, argv, str)
|
1526
|
+
int argc;
|
1527
|
+
VALUE *argv;
|
1528
|
+
VALUE str;
|
1529
|
+
{
|
1530
|
+
mm_ipc *i_mm;
|
1531
|
+
|
1532
|
+
GetMmap(str, i_mm, MM_MODIFY);
|
1533
|
+
if (argc == 3) {
|
1534
|
+
long beg, len;
|
1535
|
+
|
1536
|
+
#if HAVE_RB_DEFINE_ALLOC_FUNC
|
1537
|
+
if (TYPE(argv[0]) == T_REGEXP) {
|
1538
|
+
mm_subpat_set(str, argv[0], NUM2INT(argv[1]), argv[2]);
|
1539
|
+
}
|
1540
|
+
else
|
1541
|
+
#endif
|
1542
|
+
{
|
1543
|
+
beg = NUM2INT(argv[0]);
|
1544
|
+
len = NUM2INT(argv[1]);
|
1545
|
+
mm_update(i_mm, beg, len, argv[2]);
|
1546
|
+
}
|
1547
|
+
return argv[2];
|
1548
|
+
}
|
1549
|
+
if (argc != 2) {
|
1550
|
+
rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc);
|
1551
|
+
}
|
1552
|
+
return mm_aset(str, argv[0], argv[1]);
|
1553
|
+
}
|
1554
|
+
|
1555
|
+
#if HAVE_RB_STR_INSERT
|
1556
|
+
|
1557
|
+
/*
|
1558
|
+
* call-seq: insert(index, str)
|
1559
|
+
*
|
1560
|
+
* insert <em>str</em> at <em>index</em>
|
1561
|
+
*/
|
1562
|
+
static VALUE
|
1563
|
+
mm_insert(str, idx, str2)
|
1564
|
+
VALUE str, idx, str2;
|
1565
|
+
{
|
1566
|
+
mm_ipc *i_mm;
|
1567
|
+
long pos = NUM2LONG(idx);
|
1568
|
+
|
1569
|
+
GetMmap(str, i_mm, MM_MODIFY);
|
1570
|
+
if (pos == -1) {
|
1571
|
+
pos = RSTRING(str)->len;
|
1572
|
+
}
|
1573
|
+
else if (pos < 0) {
|
1574
|
+
pos++;
|
1575
|
+
}
|
1576
|
+
mm_update(i_mm, pos, 0, str2);
|
1577
|
+
return str;
|
1578
|
+
}
|
1579
|
+
|
1580
|
+
#endif
|
1581
|
+
|
1582
|
+
static VALUE mm_aref_m _((int, VALUE *, VALUE));
|
1583
|
+
|
1584
|
+
/*
|
1585
|
+
* call-seq: slice!(str)
|
1586
|
+
*
|
1587
|
+
* delete the specified portion of the file
|
1588
|
+
*/
|
1589
|
+
static VALUE
|
1590
|
+
mm_slice_bang(argc, argv, str)
|
1591
|
+
int argc;
|
1592
|
+
VALUE *argv;
|
1593
|
+
VALUE str;
|
1594
|
+
{
|
1595
|
+
VALUE result;
|
1596
|
+
VALUE buf[3];
|
1597
|
+
int i;
|
1598
|
+
|
1599
|
+
if (argc < 1 || 2 < argc) {
|
1600
|
+
rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)", argc);
|
1601
|
+
}
|
1602
|
+
for (i = 0; i < argc; i++) {
|
1603
|
+
buf[i] = argv[i];
|
1604
|
+
}
|
1605
|
+
buf[i] = rb_str_new(0,0);
|
1606
|
+
result = mm_aref_m(argc, buf, str);
|
1607
|
+
if (!NIL_P(result)) {
|
1608
|
+
mm_aset_m(argc+1, buf, str);
|
1609
|
+
}
|
1610
|
+
return result;
|
1611
|
+
}
|
1612
|
+
|
1613
|
+
static VALUE
|
1614
|
+
mm_cat(str, ptr, len)
|
1615
|
+
VALUE str;
|
1616
|
+
const char *ptr;
|
1617
|
+
long len;
|
1618
|
+
{
|
1619
|
+
mm_ipc *i_mm;
|
1620
|
+
char *sptr;
|
1621
|
+
|
1622
|
+
GetMmap(str, i_mm, MM_MODIFY);
|
1623
|
+
if (len > 0) {
|
1624
|
+
int poffset = -1;
|
1625
|
+
sptr = (char *)i_mm->t->addr;
|
1626
|
+
|
1627
|
+
if (sptr <= ptr &&
|
1628
|
+
ptr < sptr + i_mm->t->real) {
|
1629
|
+
poffset = ptr - sptr;
|
1630
|
+
}
|
1631
|
+
mm_lock(i_mm, Qtrue);
|
1632
|
+
mm_realloc(i_mm, i_mm->t->real + len);
|
1633
|
+
sptr = (char *)i_mm->t->addr;
|
1634
|
+
if (ptr) {
|
1635
|
+
if (poffset >= 0) ptr = sptr + poffset;
|
1636
|
+
memcpy(sptr + i_mm->t->real, ptr, len);
|
1637
|
+
}
|
1638
|
+
i_mm->t->real += len;
|
1639
|
+
mm_unlock(i_mm);
|
1640
|
+
}
|
1641
|
+
return str;
|
1642
|
+
}
|
1643
|
+
|
1644
|
+
static VALUE
|
1645
|
+
mm_append(str1, str2)
|
1646
|
+
VALUE str1, str2;
|
1647
|
+
{
|
1648
|
+
str2 = rb_str_to_str(str2);
|
1649
|
+
str1 = mm_cat(str1, StringValuePtr(str2), RSTRING(str2)->len);
|
1650
|
+
return str1;
|
1651
|
+
}
|
1652
|
+
|
1653
|
+
/*
|
1654
|
+
* Document-method: concat
|
1655
|
+
* Document-method: <<
|
1656
|
+
*
|
1657
|
+
* call-seq: concat(other)
|
1658
|
+
*
|
1659
|
+
* append the contents of <em>other</em>
|
1660
|
+
*/
|
1661
|
+
static VALUE
|
1662
|
+
mm_concat(str1, str2)
|
1663
|
+
VALUE str1, str2;
|
1664
|
+
{
|
1665
|
+
if (FIXNUM_P(str2)) {
|
1666
|
+
int i = FIX2INT(str2);
|
1667
|
+
if (0 <= i && i <= 0xff) { /* byte */
|
1668
|
+
char c = i;
|
1669
|
+
return mm_cat(str1, &c, 1);
|
1670
|
+
}
|
1671
|
+
}
|
1672
|
+
str1 = mm_append(str1, str2);
|
1673
|
+
return str1;
|
1674
|
+
}
|
1675
|
+
|
1676
|
+
#ifndef HAVE_RB_STR_LSTRIP
|
1677
|
+
|
1678
|
+
/*
|
1679
|
+
* call-seq: strip!
|
1680
|
+
*
|
1681
|
+
* removes leading and trailing whitespace
|
1682
|
+
*/
|
1683
|
+
static VALUE
|
1684
|
+
mm_strip_bang(str)
|
1685
|
+
VALUE str;
|
1686
|
+
{
|
1687
|
+
char *s, *t, *e;
|
1688
|
+
mm_ipc *i_mm;
|
1689
|
+
|
1690
|
+
GetMmap(str, i_mm, MM_MODIFY);
|
1691
|
+
mm_lock(i_mm, Qtrue);
|
1692
|
+
s = (char *)i_mm->t->addr;
|
1693
|
+
e = t = s + i_mm->t->real;
|
1694
|
+
while (s < t && ISSPACE(*s)) s++;
|
1695
|
+
t--;
|
1696
|
+
while (s <= t && ISSPACE(*t)) t--;
|
1697
|
+
t++;
|
1698
|
+
|
1699
|
+
if (i_mm->t->real != (t - s) && (i_mm->t->flag & MM_FIXED)) {
|
1700
|
+
mm_unlock(i_mm);
|
1701
|
+
rb_raise(rb_eTypeError, "try to change the size of a fixed map");
|
1702
|
+
}
|
1703
|
+
i_mm->t->real = t-s;
|
1704
|
+
if (s > (char *)i_mm->t->addr) {
|
1705
|
+
memmove(i_mm->t->addr, s, i_mm->t->real);
|
1706
|
+
((char *)i_mm->t->addr)[i_mm->t->real] = '\0';
|
1707
|
+
}
|
1708
|
+
else if (t < e) {
|
1709
|
+
((char *)i_mm->t->addr)[i_mm->t->real] = '\0';
|
1710
|
+
}
|
1711
|
+
else {
|
1712
|
+
str = Qnil;
|
1713
|
+
}
|
1714
|
+
mm_unlock(i_mm);
|
1715
|
+
return str;
|
1716
|
+
}
|
1717
|
+
|
1718
|
+
#else
|
1719
|
+
|
1720
|
+
/*
|
1721
|
+
* call-seq: lstrip!
|
1722
|
+
*
|
1723
|
+
* removes leading whitespace
|
1724
|
+
*/
|
1725
|
+
static VALUE
|
1726
|
+
mm_lstrip_bang(str)
|
1727
|
+
VALUE str;
|
1728
|
+
{
|
1729
|
+
char *s, *t, *e;
|
1730
|
+
mm_ipc *i_mm;
|
1731
|
+
|
1732
|
+
GetMmap(str, i_mm, MM_MODIFY);
|
1733
|
+
mm_lock(i_mm, Qtrue);
|
1734
|
+
s = (char *)i_mm->t->addr;
|
1735
|
+
e = t = s + i_mm->t->real;
|
1736
|
+
while (s < t && ISSPACE(*s)) s++;
|
1737
|
+
|
1738
|
+
if (i_mm->t->real != (size_t)(t - s) && (i_mm->t->flag & MM_FIXED)) {
|
1739
|
+
mm_unlock(i_mm);
|
1740
|
+
rb_raise(rb_eTypeError, "try to change the size of a fixed map");
|
1741
|
+
}
|
1742
|
+
i_mm->t->real = t - s;
|
1743
|
+
if (s > (char *)i_mm->t->addr) {
|
1744
|
+
memmove(i_mm->t->addr, s, i_mm->t->real);
|
1745
|
+
((char *)i_mm->t->addr)[i_mm->t->real] = '\0';
|
1746
|
+
mm_unlock(i_mm);
|
1747
|
+
return str;
|
1748
|
+
}
|
1749
|
+
mm_unlock(i_mm);
|
1750
|
+
return Qnil;
|
1751
|
+
}
|
1752
|
+
|
1753
|
+
/*
|
1754
|
+
* call-seq: rstrip!
|
1755
|
+
*
|
1756
|
+
* removes trailing whitespace
|
1757
|
+
*/
|
1758
|
+
static VALUE
|
1759
|
+
mm_rstrip_bang(str)
|
1760
|
+
VALUE str;
|
1761
|
+
{
|
1762
|
+
char *s, *t, *e;
|
1763
|
+
mm_ipc *i_mm;
|
1764
|
+
|
1765
|
+
GetMmap(str, i_mm, MM_MODIFY);
|
1766
|
+
mm_lock(i_mm, Qtrue);
|
1767
|
+
s = (char *)i_mm->t->addr;
|
1768
|
+
e = t = s + i_mm->t->real;
|
1769
|
+
t--;
|
1770
|
+
while (s <= t && ISSPACE(*t)) t--;
|
1771
|
+
t++;
|
1772
|
+
if (i_mm->t->real != (size_t)(t - s) && (i_mm->t->flag & MM_FIXED)) {
|
1773
|
+
mm_unlock(i_mm);
|
1774
|
+
rb_raise(rb_eTypeError, "try to change the size of a fixed map");
|
1775
|
+
}
|
1776
|
+
i_mm->t->real = t - s;
|
1777
|
+
if (t < e) {
|
1778
|
+
((char *)i_mm->t->addr)[i_mm->t->real] = '\0';
|
1779
|
+
mm_unlock(i_mm);
|
1780
|
+
return str;
|
1781
|
+
}
|
1782
|
+
mm_unlock(i_mm);
|
1783
|
+
return Qnil;
|
1784
|
+
}
|
1785
|
+
|
1786
|
+
static VALUE
|
1787
|
+
mm_strip_bang(str)
|
1788
|
+
VALUE str;
|
1789
|
+
{
|
1790
|
+
VALUE l = mm_lstrip_bang(str);
|
1791
|
+
VALUE r = mm_rstrip_bang(str);
|
1792
|
+
|
1793
|
+
if (NIL_P(l) && NIL_P(r)) return Qnil;
|
1794
|
+
return str;
|
1795
|
+
}
|
1796
|
+
|
1797
|
+
#endif
|
1798
|
+
|
1799
|
+
#define MmapStr(b, recycle) \
|
1800
|
+
do { \
|
1801
|
+
recycle = 0; \
|
1802
|
+
if (TYPE(b) == T_DATA && RDATA(b)->dfree == (RUBY_DATA_FUNC)mm_free) { \
|
1803
|
+
recycle = 1; \
|
1804
|
+
b = mm_str(b, MM_ORIGIN); \
|
1805
|
+
} \
|
1806
|
+
else { \
|
1807
|
+
b = rb_str_to_str(b); \
|
1808
|
+
} \
|
1809
|
+
} while (0);
|
1810
|
+
|
1811
|
+
|
1812
|
+
/*
|
1813
|
+
* call-seq: <=>(other)
|
1814
|
+
*
|
1815
|
+
* comparison : return -1, 0, 1
|
1816
|
+
*/
|
1817
|
+
static VALUE
|
1818
|
+
mm_cmp(a, b)
|
1819
|
+
VALUE a, b;
|
1820
|
+
{
|
1821
|
+
int result;
|
1822
|
+
int recycle = 0;
|
1823
|
+
|
1824
|
+
a = mm_str(a, MM_ORIGIN);
|
1825
|
+
MmapStr(b, recycle);
|
1826
|
+
result = rb_str_cmp(a, b);
|
1827
|
+
rb_gc_force_recycle(a);
|
1828
|
+
if (recycle) rb_gc_force_recycle(b);
|
1829
|
+
return INT2FIX(result);
|
1830
|
+
}
|
1831
|
+
|
1832
|
+
#if HAVE_RB_STR_CASECMP
|
1833
|
+
|
1834
|
+
/*
|
1835
|
+
* call-seq: casecmp(other)
|
1836
|
+
*
|
1837
|
+
* only with ruby >= 1.7.1
|
1838
|
+
*/
|
1839
|
+
static VALUE
|
1840
|
+
mm_casecmp(a, b)
|
1841
|
+
VALUE a, b;
|
1842
|
+
{
|
1843
|
+
VALUE result;
|
1844
|
+
int recycle = 0;
|
1845
|
+
|
1846
|
+
a = mm_str(a, MM_ORIGIN);
|
1847
|
+
MmapStr(b, recycle);
|
1848
|
+
result = rb_funcall2(a, rb_intern("casecmp"), 1, &b);
|
1849
|
+
rb_gc_force_recycle(a);
|
1850
|
+
if (recycle) rb_gc_force_recycle(b);
|
1851
|
+
return result;
|
1852
|
+
}
|
1853
|
+
|
1854
|
+
#endif
|
1855
|
+
|
1856
|
+
/*
|
1857
|
+
* Document-method: ==
|
1858
|
+
* Document-method: ===
|
1859
|
+
*
|
1860
|
+
* call-seq: ==
|
1861
|
+
*
|
1862
|
+
* comparison
|
1863
|
+
*/
|
1864
|
+
static VALUE
|
1865
|
+
mm_equal(a, b)
|
1866
|
+
VALUE a, b;
|
1867
|
+
{
|
1868
|
+
VALUE result;
|
1869
|
+
mm_ipc *i_mm, *u_mm;
|
1870
|
+
|
1871
|
+
if (a == b) return Qtrue;
|
1872
|
+
if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RUBY_DATA_FUNC)mm_free)
|
1873
|
+
return Qfalse;
|
1874
|
+
|
1875
|
+
GetMmap(a, i_mm, 0);
|
1876
|
+
GetMmap(b, u_mm, 0);
|
1877
|
+
if (i_mm->t->real != u_mm->t->real)
|
1878
|
+
return Qfalse;
|
1879
|
+
a = mm_str(a, MM_ORIGIN);
|
1880
|
+
b = mm_str(b, MM_ORIGIN);
|
1881
|
+
result = rb_funcall2(a, rb_intern("=="), 1, &b);
|
1882
|
+
rb_gc_force_recycle(a);
|
1883
|
+
rb_gc_force_recycle(b);
|
1884
|
+
return result;
|
1885
|
+
}
|
1886
|
+
|
1887
|
+
/*
|
1888
|
+
* call-seq: eql?(other)
|
1889
|
+
*
|
1890
|
+
* Is this eql? to +other+ ?
|
1891
|
+
*/
|
1892
|
+
static VALUE
|
1893
|
+
mm_eql(a, b)
|
1894
|
+
VALUE a, b;
|
1895
|
+
{
|
1896
|
+
VALUE result;
|
1897
|
+
mm_ipc *i_mm, *u_mm;
|
1898
|
+
|
1899
|
+
if (a == b) return Qtrue;
|
1900
|
+
if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RUBY_DATA_FUNC)mm_free)
|
1901
|
+
return Qfalse;
|
1902
|
+
|
1903
|
+
GetMmap(a, i_mm, 0);
|
1904
|
+
GetMmap(b, u_mm, 0);
|
1905
|
+
if (i_mm->t->real != u_mm->t->real)
|
1906
|
+
return Qfalse;
|
1907
|
+
a = mm_str(a, MM_ORIGIN);
|
1908
|
+
b = mm_str(b, MM_ORIGIN);
|
1909
|
+
result = rb_funcall2(a, rb_intern("eql?"), 1, &b);
|
1910
|
+
rb_gc_force_recycle(a);
|
1911
|
+
rb_gc_force_recycle(b);
|
1912
|
+
return result;
|
1913
|
+
}
|
1914
|
+
|
1915
|
+
/*
|
1916
|
+
* call-seq: hash
|
1917
|
+
*
|
1918
|
+
* Get the hash value
|
1919
|
+
*/
|
1920
|
+
static VALUE
|
1921
|
+
mm_hash(a)
|
1922
|
+
VALUE a;
|
1923
|
+
{
|
1924
|
+
VALUE b;
|
1925
|
+
int res;
|
1926
|
+
|
1927
|
+
b = mm_str(a, MM_ORIGIN);
|
1928
|
+
res = rb_str_hash(b);
|
1929
|
+
rb_gc_force_recycle(b);
|
1930
|
+
return INT2FIX(res);
|
1931
|
+
}
|
1932
|
+
|
1933
|
+
/*
|
1934
|
+
* Document-method: length
|
1935
|
+
* Document-method: size
|
1936
|
+
*
|
1937
|
+
* return the size of the file
|
1938
|
+
*/
|
1939
|
+
static VALUE
|
1940
|
+
mm_size(a)
|
1941
|
+
VALUE a;
|
1942
|
+
{
|
1943
|
+
mm_ipc *i_mm;
|
1944
|
+
|
1945
|
+
GetMmap(a, i_mm, 0);
|
1946
|
+
return UINT2NUM(i_mm->t->real);
|
1947
|
+
}
|
1948
|
+
|
1949
|
+
/*
|
1950
|
+
* call-seq: empty?
|
1951
|
+
*
|
1952
|
+
* return <em>true</em> if the file is empty
|
1953
|
+
*/
|
1954
|
+
static VALUE
|
1955
|
+
mm_empty(a)
|
1956
|
+
VALUE a;
|
1957
|
+
{
|
1958
|
+
mm_ipc *i_mm;
|
1959
|
+
|
1960
|
+
GetMmap(a, i_mm, 0);
|
1961
|
+
if (i_mm->t->real == 0) return Qtrue;
|
1962
|
+
return Qfalse;
|
1963
|
+
}
|
1964
|
+
|
1965
|
+
static VALUE
|
1966
|
+
mm_protect_bang(t)
|
1967
|
+
VALUE *t;
|
1968
|
+
{
|
1969
|
+
return rb_funcall2(t[0], (ID)t[1], (int)t[2], (VALUE *)t[3]);
|
1970
|
+
}
|
1971
|
+
|
1972
|
+
static VALUE
|
1973
|
+
mm_recycle(str)
|
1974
|
+
VALUE str;
|
1975
|
+
{
|
1976
|
+
rb_gc_force_recycle(str);
|
1977
|
+
return str;
|
1978
|
+
}
|
1979
|
+
|
1980
|
+
static VALUE
|
1981
|
+
mm_i_bang(bang_st)
|
1982
|
+
mm_bang *bang_st;
|
1983
|
+
{
|
1984
|
+
VALUE str, res;
|
1985
|
+
mm_ipc *i_mm;
|
1986
|
+
|
1987
|
+
str = mm_str(bang_st->obj, bang_st->flag);
|
1988
|
+
if (bang_st->flag & MM_PROTECT) {
|
1989
|
+
VALUE tmp[4];
|
1990
|
+
tmp[0] = str;
|
1991
|
+
tmp[1] = (VALUE)bang_st->id;
|
1992
|
+
tmp[2] = (VALUE)bang_st->argc;
|
1993
|
+
tmp[3] = (VALUE)bang_st->argv;
|
1994
|
+
res = rb_ensure(mm_protect_bang, (VALUE)tmp, mm_recycle, str);
|
1995
|
+
}
|
1996
|
+
else {
|
1997
|
+
res = rb_funcall2(str, bang_st->id, bang_st->argc, bang_st->argv);
|
1998
|
+
rb_gc_force_recycle(str);
|
1999
|
+
}
|
2000
|
+
if (res != Qnil) {
|
2001
|
+
GetMmap(bang_st->obj, i_mm, 0);
|
2002
|
+
i_mm->t->real = RSTRING(str)->len;
|
2003
|
+
}
|
2004
|
+
return res;
|
2005
|
+
}
|
2006
|
+
|
2007
|
+
|
2008
|
+
static VALUE
|
2009
|
+
mm_bang_i(obj, flag, id, argc, argv)
|
2010
|
+
VALUE obj, *argv;
|
2011
|
+
int flag, id, argc;
|
2012
|
+
{
|
2013
|
+
VALUE res;
|
2014
|
+
mm_ipc *i_mm;
|
2015
|
+
mm_bang bang_st;
|
2016
|
+
|
2017
|
+
GetMmap(obj, i_mm, 0);
|
2018
|
+
if ((flag & MM_CHANGE) && (i_mm->t->flag & MM_FIXED)) {
|
2019
|
+
rb_raise(rb_eTypeError, "try to change the size of a fixed map");
|
2020
|
+
}
|
2021
|
+
bang_st.obj = obj;
|
2022
|
+
bang_st.flag = flag;
|
2023
|
+
bang_st.id = id;
|
2024
|
+
bang_st.argc = argc;
|
2025
|
+
bang_st.argv = argv;
|
2026
|
+
if (i_mm->t->flag & MM_IPC) {
|
2027
|
+
mm_lock(i_mm, Qtrue);
|
2028
|
+
res = rb_ensure(mm_i_bang, (VALUE)&bang_st, mm_vunlock, obj);
|
2029
|
+
}
|
2030
|
+
else {
|
2031
|
+
res = mm_i_bang(&bang_st);
|
2032
|
+
}
|
2033
|
+
if (res == Qnil) return res;
|
2034
|
+
return (flag & MM_ORIGIN)?res:obj;
|
2035
|
+
|
2036
|
+
}
|
2037
|
+
|
2038
|
+
#if HAVE_RB_STR_MATCH
|
2039
|
+
|
2040
|
+
/*
|
2041
|
+
* call-seq: match(pattern)
|
2042
|
+
*
|
2043
|
+
* convert <em>pattern</em> to a <em>Regexp</em> and then call
|
2044
|
+
* <em>match</em> on <em>self</em>
|
2045
|
+
*/
|
2046
|
+
static VALUE
|
2047
|
+
mm_match_m(a, b)
|
2048
|
+
VALUE a, b;
|
2049
|
+
{
|
2050
|
+
return mm_bang_i(a, MM_ORIGIN, rb_intern("match"), 1, &b);
|
2051
|
+
}
|
2052
|
+
|
2053
|
+
#endif
|
2054
|
+
|
2055
|
+
/*
|
2056
|
+
* call-seq: upcase!
|
2057
|
+
*
|
2058
|
+
* replaces all lowercase characters to downcase characters
|
2059
|
+
*/
|
2060
|
+
static VALUE
|
2061
|
+
mm_upcase_bang(a)
|
2062
|
+
VALUE a;
|
2063
|
+
{
|
2064
|
+
return mm_bang_i(a, MM_MODIFY, rb_intern("upcase!"), 0, 0);
|
2065
|
+
}
|
2066
|
+
|
2067
|
+
/*
|
2068
|
+
* call-seq: downcase!
|
2069
|
+
*
|
2070
|
+
* change all uppercase character to lowercase character
|
2071
|
+
*/
|
2072
|
+
static VALUE
|
2073
|
+
mm_downcase_bang(a)
|
2074
|
+
VALUE a;
|
2075
|
+
{
|
2076
|
+
return mm_bang_i(a, MM_MODIFY, rb_intern("downcase!"), 0, 0);
|
2077
|
+
}
|
2078
|
+
|
2079
|
+
/*
|
2080
|
+
* call-seq: capitalize!
|
2081
|
+
*
|
2082
|
+
* change the first character to uppercase letter
|
2083
|
+
*/
|
2084
|
+
static VALUE
|
2085
|
+
mm_capitalize_bang(a)
|
2086
|
+
VALUE a;
|
2087
|
+
{
|
2088
|
+
return mm_bang_i(a, MM_MODIFY, rb_intern("capitalize!"), 0, 0);
|
2089
|
+
}
|
2090
|
+
|
2091
|
+
/*
|
2092
|
+
* call-seq: swapcase!
|
2093
|
+
*
|
2094
|
+
* replaces all lowercase characters to uppercase characters, and vice-versa
|
2095
|
+
*/
|
2096
|
+
static VALUE
|
2097
|
+
mm_swapcase_bang(a)
|
2098
|
+
VALUE a;
|
2099
|
+
{
|
2100
|
+
return mm_bang_i(a, MM_MODIFY, rb_intern("swapcase!"), 0, 0);
|
2101
|
+
}
|
2102
|
+
|
2103
|
+
/*
|
2104
|
+
* call-seq: reverse!
|
2105
|
+
*
|
2106
|
+
* reverse the content of the file
|
2107
|
+
*/
|
2108
|
+
static VALUE
|
2109
|
+
mm_reverse_bang(a)
|
2110
|
+
VALUE a;
|
2111
|
+
{
|
2112
|
+
return mm_bang_i(a, MM_MODIFY, rb_intern("reverse!"), 0, 0);
|
2113
|
+
}
|
2114
|
+
|
2115
|
+
/*
|
2116
|
+
* call-seq: chop!
|
2117
|
+
*
|
2118
|
+
* chop off the last character
|
2119
|
+
*/
|
2120
|
+
static VALUE
|
2121
|
+
mm_chop_bang(a)
|
2122
|
+
VALUE a;
|
2123
|
+
{
|
2124
|
+
return mm_bang_i(a, MM_CHANGE, rb_intern("chop!"), 0, 0);
|
2125
|
+
}
|
2126
|
+
|
2127
|
+
/*
|
2128
|
+
* call-seq: chomp!(rs = $/)
|
2129
|
+
*
|
2130
|
+
* chop off the line ending character, specified by <em>rs</em>
|
2131
|
+
*/
|
2132
|
+
static VALUE
|
2133
|
+
mm_chomp_bang(argc, argv, obj)
|
2134
|
+
int argc;
|
2135
|
+
VALUE *argv, obj;
|
2136
|
+
{
|
2137
|
+
return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("chomp!"), argc, argv);
|
2138
|
+
}
|
2139
|
+
|
2140
|
+
/*
|
2141
|
+
* call-seq: delete!(str)
|
2142
|
+
*
|
2143
|
+
* delete every characters included in <em>str</em>
|
2144
|
+
*/
|
2145
|
+
static VALUE
|
2146
|
+
mm_delete_bang(argc, argv, obj)
|
2147
|
+
int argc;
|
2148
|
+
VALUE *argv, obj;
|
2149
|
+
{
|
2150
|
+
return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("delete!"), argc, argv);
|
2151
|
+
}
|
2152
|
+
|
2153
|
+
/*
|
2154
|
+
* squeeze!(str)
|
2155
|
+
*
|
2156
|
+
* squeezes sequences of the same characters which is included in <em>str</em>
|
2157
|
+
*/
|
2158
|
+
static VALUE
|
2159
|
+
mm_squeeze_bang(argc, argv, obj)
|
2160
|
+
int argc;
|
2161
|
+
VALUE *argv, obj;
|
2162
|
+
{
|
2163
|
+
return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("squeeze!"), argc, argv);
|
2164
|
+
}
|
2165
|
+
|
2166
|
+
/*
|
2167
|
+
* call-seq: tr!(search, replace)
|
2168
|
+
*
|
2169
|
+
* translate the character from <em>search</em> to <em>replace</em>
|
2170
|
+
*/
|
2171
|
+
static VALUE
|
2172
|
+
mm_tr_bang(obj, a, b)
|
2173
|
+
VALUE obj, a, b;
|
2174
|
+
{
|
2175
|
+
VALUE tmp[2];
|
2176
|
+
tmp[0] = a;
|
2177
|
+
tmp[1] = b;
|
2178
|
+
return mm_bang_i(obj, MM_MODIFY | MM_PROTECT, rb_intern("tr!"), 2, tmp);
|
2179
|
+
}
|
2180
|
+
|
2181
|
+
/*
|
2182
|
+
* call-seq: tr_s!(search, replace)
|
2183
|
+
*
|
2184
|
+
* translate the character from <em>search</em> to <em>replace</em>, then
|
2185
|
+
* squeeze sequence of the same characters
|
2186
|
+
*/
|
2187
|
+
static VALUE
|
2188
|
+
mm_tr_s_bang(obj, a, b)
|
2189
|
+
VALUE obj, a, b;
|
2190
|
+
{
|
2191
|
+
VALUE tmp[2];
|
2192
|
+
tmp[0] = a;
|
2193
|
+
tmp[1] = b;
|
2194
|
+
return mm_bang_i(obj, MM_CHANGE | MM_PROTECT, rb_intern("tr_s!"), 2, tmp);
|
2195
|
+
}
|
2196
|
+
|
2197
|
+
/*
|
2198
|
+
* call-seq: crypt
|
2199
|
+
*
|
2200
|
+
* crypt with <em>salt</em>
|
2201
|
+
*/
|
2202
|
+
static VALUE
|
2203
|
+
mm_crypt(a, b)
|
2204
|
+
VALUE a, b;
|
2205
|
+
{
|
2206
|
+
return mm_bang_i(a, MM_ORIGIN, rb_intern("crypt"), 1, &b);
|
2207
|
+
}
|
2208
|
+
|
2209
|
+
/*
|
2210
|
+
* call-seq: include?(other)
|
2211
|
+
*
|
2212
|
+
* return <em>true</em> if <em>other</em> is found
|
2213
|
+
*/
|
2214
|
+
static VALUE
|
2215
|
+
mm_include(a, b)
|
2216
|
+
VALUE a, b;
|
2217
|
+
{
|
2218
|
+
return mm_bang_i(a, MM_ORIGIN, rb_intern("include?"), 1, &b);
|
2219
|
+
}
|
2220
|
+
|
2221
|
+
/*
|
2222
|
+
* call-seq: index
|
2223
|
+
*
|
2224
|
+
* return the index of <em>substr</em>
|
2225
|
+
*/
|
2226
|
+
static VALUE
|
2227
|
+
mm_index(argc, argv, obj)
|
2228
|
+
int argc;
|
2229
|
+
VALUE *argv, obj;
|
2230
|
+
{
|
2231
|
+
return mm_bang_i(obj, MM_ORIGIN, rb_intern("index"), argc, argv);
|
2232
|
+
}
|
2233
|
+
|
2234
|
+
/*
|
2235
|
+
* call-seq: rindex(sibstr, pos = nil)
|
2236
|
+
*
|
2237
|
+
* return the index of the last occurrence of <em>substr</em>
|
2238
|
+
*/
|
2239
|
+
static VALUE
|
2240
|
+
mm_rindex(argc, argv, obj)
|
2241
|
+
int argc;
|
2242
|
+
VALUE *argv, obj;
|
2243
|
+
{
|
2244
|
+
return mm_bang_i(obj, MM_ORIGIN, rb_intern("rindex"), argc, argv);
|
2245
|
+
}
|
2246
|
+
|
2247
|
+
/*
|
2248
|
+
* Document-method: []
|
2249
|
+
* Document-method: slice
|
2250
|
+
*
|
2251
|
+
* call-seq: [](args)
|
2252
|
+
*
|
2253
|
+
* Element reference - with the following syntax:
|
2254
|
+
*
|
2255
|
+
* self[nth]
|
2256
|
+
*
|
2257
|
+
* retrieve the <em>nth</em> character
|
2258
|
+
*
|
2259
|
+
* self[start..last]
|
2260
|
+
*
|
2261
|
+
* return a substring from <em>start</em> to <em>last</em>
|
2262
|
+
*
|
2263
|
+
* self[start, length]
|
2264
|
+
*
|
2265
|
+
* return a substring of <em>lenght</em> characters from <em>start</em>
|
2266
|
+
*/
|
2267
|
+
static VALUE
|
2268
|
+
mm_aref_m(argc, argv, obj)
|
2269
|
+
int argc;
|
2270
|
+
VALUE *argv, obj;
|
2271
|
+
{
|
2272
|
+
return mm_bang_i(obj, MM_ORIGIN, rb_intern("[]"), argc, argv);
|
2273
|
+
}
|
2274
|
+
|
2275
|
+
/*
|
2276
|
+
* call-seq: sum(bits = 16)
|
2277
|
+
*
|
2278
|
+
* return a checksum
|
2279
|
+
*/
|
2280
|
+
static VALUE
|
2281
|
+
mm_sum(argc, argv, obj)
|
2282
|
+
int argc;
|
2283
|
+
VALUE *argv, obj;
|
2284
|
+
{
|
2285
|
+
return mm_bang_i(obj, MM_ORIGIN, rb_intern("sum"), argc, argv);
|
2286
|
+
}
|
2287
|
+
|
2288
|
+
/*
|
2289
|
+
* call-seq: split(sep, limit = 0)
|
2290
|
+
*
|
2291
|
+
* splits into a list of strings and return this array
|
2292
|
+
*/
|
2293
|
+
static VALUE
|
2294
|
+
mm_split(argc, argv, obj)
|
2295
|
+
int argc;
|
2296
|
+
VALUE *argv, obj;
|
2297
|
+
{
|
2298
|
+
return mm_bang_i(obj, MM_ORIGIN, rb_intern("split"), argc, argv);
|
2299
|
+
}
|
2300
|
+
|
2301
|
+
/*
|
2302
|
+
* call-seq: count(o1, *args)
|
2303
|
+
*
|
2304
|
+
* each parameter defines a set of character to count
|
2305
|
+
*/
|
2306
|
+
static VALUE
|
2307
|
+
mm_count(argc, argv, obj)
|
2308
|
+
int argc;
|
2309
|
+
VALUE *argv, obj;
|
2310
|
+
{
|
2311
|
+
return mm_bang_i(obj, MM_ORIGIN, rb_intern("count"), argc, argv);
|
2312
|
+
}
|
2313
|
+
|
2314
|
+
static VALUE
|
2315
|
+
mm_internal_each(tmp)
|
2316
|
+
VALUE *tmp;
|
2317
|
+
{
|
2318
|
+
return rb_funcall2(tmp[0], (ID)tmp[1], (int)tmp[2], (VALUE *)tmp[3]);
|
2319
|
+
}
|
2320
|
+
|
2321
|
+
/*
|
2322
|
+
* call-seq: scan(pattern, &block)
|
2323
|
+
*
|
2324
|
+
* return an array of all occurence matched by <em>pattern</em>
|
2325
|
+
*/
|
2326
|
+
static VALUE
|
2327
|
+
mm_scan(obj, a)
|
2328
|
+
VALUE obj, a;
|
2329
|
+
{
|
2330
|
+
VALUE tmp[4];
|
2331
|
+
|
2332
|
+
if (!rb_block_given_p()) {
|
2333
|
+
return rb_funcall(mm_str(obj, MM_ORIGIN), rb_intern("scan"), 1, a);
|
2334
|
+
}
|
2335
|
+
tmp[0] = mm_str(obj, MM_ORIGIN);
|
2336
|
+
tmp[1] = (VALUE)rb_intern("scan");
|
2337
|
+
tmp[2] = (VALUE)1;
|
2338
|
+
tmp[3] = (VALUE)&a;
|
2339
|
+
rb_iterate(mm_internal_each, (VALUE)tmp, rb_yield, 0);
|
2340
|
+
return obj;
|
2341
|
+
}
|
2342
|
+
|
2343
|
+
/*
|
2344
|
+
* Document-method: each
|
2345
|
+
* Document-method: each_line
|
2346
|
+
*
|
2347
|
+
* call-seq:
|
2348
|
+
* each(rs = $/, &block)
|
2349
|
+
*
|
2350
|
+
* iterate on each line
|
2351
|
+
*/
|
2352
|
+
static VALUE
|
2353
|
+
mm_each_line(argc, argv, obj)
|
2354
|
+
int argc;
|
2355
|
+
VALUE obj, *argv;
|
2356
|
+
{
|
2357
|
+
VALUE tmp[4];
|
2358
|
+
|
2359
|
+
tmp[0] = mm_str(obj, MM_ORIGIN);
|
2360
|
+
tmp[1] = (VALUE)rb_intern("each_line");
|
2361
|
+
tmp[2] = (VALUE)argc;
|
2362
|
+
tmp[3] = (VALUE)argv;
|
2363
|
+
rb_iterate(mm_internal_each, (VALUE)tmp, rb_yield, 0);
|
2364
|
+
return obj;
|
2365
|
+
}
|
2366
|
+
|
2367
|
+
/*
|
2368
|
+
* call-seq: each_byte(&block)
|
2369
|
+
*
|
2370
|
+
* iterate on each byte
|
2371
|
+
*/
|
2372
|
+
static VALUE
|
2373
|
+
mm_each_byte(argc, argv, obj)
|
2374
|
+
int argc;
|
2375
|
+
VALUE obj, *argv;
|
2376
|
+
{
|
2377
|
+
VALUE tmp[4];
|
2378
|
+
|
2379
|
+
tmp[0] = mm_str(obj, MM_ORIGIN);
|
2380
|
+
tmp[1] = (VALUE)rb_intern("each_byte");
|
2381
|
+
tmp[2] = (VALUE)argc;
|
2382
|
+
tmp[3] = (VALUE)argv;
|
2383
|
+
rb_iterate(mm_internal_each, (VALUE)tmp, rb_yield, 0);
|
2384
|
+
return obj;
|
2385
|
+
}
|
2386
|
+
|
2387
|
+
/*
|
2388
|
+
* Document-method: lockall
|
2389
|
+
* Document-method: mlockall
|
2390
|
+
*
|
2391
|
+
* call-seq:
|
2392
|
+
* lockall(flag)
|
2393
|
+
*
|
2394
|
+
* disable paging of all pages mapped. <em>flag</em> can be
|
2395
|
+
* <em>Mmap::MCL_CURRENT</em> or <em>Mmap::MCL_FUTURE</em>
|
2396
|
+
*/
|
2397
|
+
static VALUE
|
2398
|
+
mm_mlockall(obj, flag)
|
2399
|
+
VALUE obj, flag;
|
2400
|
+
{
|
2401
|
+
if (mlockall(NUM2INT(flag)) == -1) {
|
2402
|
+
rb_raise(rb_eArgError, "mlockall(%d)", errno);
|
2403
|
+
}
|
2404
|
+
return Qnil;
|
2405
|
+
}
|
2406
|
+
|
2407
|
+
/*
|
2408
|
+
* Document-method: unlockall
|
2409
|
+
* Document-method: munlockall
|
2410
|
+
*
|
2411
|
+
* call-seq: unlockall
|
2412
|
+
*
|
2413
|
+
* reenable paging
|
2414
|
+
*/
|
2415
|
+
static VALUE
|
2416
|
+
mm_munlockall(obj)
|
2417
|
+
VALUE obj;
|
2418
|
+
{
|
2419
|
+
if (munlockall() == -1) {
|
2420
|
+
rb_raise(rb_eArgError, "munlockall(%d)", errno);
|
2421
|
+
}
|
2422
|
+
return Qnil;
|
2423
|
+
}
|
2424
|
+
|
2425
|
+
/*
|
2426
|
+
* Document-method: lock
|
2427
|
+
* Document-method: mlock
|
2428
|
+
*
|
2429
|
+
* call-seq: mlock
|
2430
|
+
*
|
2431
|
+
* disable paging
|
2432
|
+
*/
|
2433
|
+
static VALUE
|
2434
|
+
mm_mlock(obj)
|
2435
|
+
VALUE obj;
|
2436
|
+
{
|
2437
|
+
mm_ipc *i_mm;
|
2438
|
+
|
2439
|
+
Data_Get_Struct(obj, mm_ipc, i_mm);
|
2440
|
+
if (i_mm->t->flag & MM_LOCK) {
|
2441
|
+
return obj;
|
2442
|
+
}
|
2443
|
+
if (i_mm->t->flag & MM_ANON) {
|
2444
|
+
rb_raise(rb_eArgError, "mlock(anonymous)");
|
2445
|
+
}
|
2446
|
+
if (mlock(i_mm->t->addr, i_mm->t->len) == -1) {
|
2447
|
+
rb_raise(rb_eArgError, "mlock(%d)", errno);
|
2448
|
+
}
|
2449
|
+
i_mm->t->flag |= MM_LOCK;
|
2450
|
+
return obj;
|
2451
|
+
}
|
2452
|
+
|
2453
|
+
/*
|
2454
|
+
* Document-method: munlock
|
2455
|
+
* Document-method: unlock
|
2456
|
+
*
|
2457
|
+
* call-seq: unlock
|
2458
|
+
*
|
2459
|
+
* reenable paging
|
2460
|
+
*/
|
2461
|
+
static VALUE
|
2462
|
+
mm_munlock(obj)
|
2463
|
+
VALUE obj;
|
2464
|
+
{
|
2465
|
+
mm_ipc *i_mm;
|
2466
|
+
|
2467
|
+
Data_Get_Struct(obj, mm_ipc, i_mm);
|
2468
|
+
if (!(i_mm->t->flag & MM_LOCK)) {
|
2469
|
+
return obj;
|
2470
|
+
}
|
2471
|
+
if (munlock(i_mm->t->addr, i_mm->t->len) == -1) {
|
2472
|
+
rb_raise(rb_eArgError, "munlock(%d)", errno);
|
2473
|
+
}
|
2474
|
+
i_mm->t->flag &= ~MM_LOCK;
|
2475
|
+
return obj;
|
2476
|
+
}
|
2477
|
+
|
2478
|
+
void
|
2479
|
+
Init_mmap()
|
2480
|
+
{
|
2481
|
+
if (rb_const_defined_at(rb_cObject, rb_intern("Mmap"))) {
|
2482
|
+
rb_raise(rb_eNameError, "class already defined");
|
2483
|
+
}
|
2484
|
+
mm_cMap = rb_define_class("Mmap", rb_cObject);
|
2485
|
+
rb_define_const(mm_cMap, "MS_SYNC", INT2FIX(MS_SYNC));
|
2486
|
+
rb_define_const(mm_cMap, "MS_ASYNC", INT2FIX(MS_ASYNC));
|
2487
|
+
rb_define_const(mm_cMap, "MS_INVALIDATE", INT2FIX(MS_INVALIDATE));
|
2488
|
+
rb_define_const(mm_cMap, "PROT_READ", INT2FIX(PROT_READ));
|
2489
|
+
rb_define_const(mm_cMap, "PROT_WRITE", INT2FIX(PROT_WRITE));
|
2490
|
+
rb_define_const(mm_cMap, "PROT_EXEC", INT2FIX(PROT_EXEC));
|
2491
|
+
rb_define_const(mm_cMap, "PROT_NONE", INT2FIX(PROT_NONE));
|
2492
|
+
rb_define_const(mm_cMap, "MAP_SHARED", INT2FIX(MAP_SHARED));
|
2493
|
+
rb_define_const(mm_cMap, "MAP_PRIVATE", INT2FIX(MAP_PRIVATE));
|
2494
|
+
#ifdef MADV_NORMAL
|
2495
|
+
rb_define_const(mm_cMap, "MADV_NORMAL", INT2FIX(MADV_NORMAL));
|
2496
|
+
rb_define_const(mm_cMap, "MADV_RANDOM", INT2FIX(MADV_RANDOM));
|
2497
|
+
rb_define_const(mm_cMap, "MADV_SEQUENTIAL", INT2FIX(MADV_SEQUENTIAL));
|
2498
|
+
rb_define_const(mm_cMap, "MADV_WILLNEED", INT2FIX(MADV_WILLNEED));
|
2499
|
+
rb_define_const(mm_cMap, "MADV_DONTNEED", INT2FIX(MADV_DONTNEED));
|
2500
|
+
#endif
|
2501
|
+
#ifdef MAP_DENYWRITE
|
2502
|
+
rb_define_const(mm_cMap, "MAP_DENYWRITE", INT2FIX(MAP_DENYWRITE));
|
2503
|
+
#endif
|
2504
|
+
#ifdef MAP_EXECUTABLE
|
2505
|
+
rb_define_const(mm_cMap, "MAP_EXECUTABLE", INT2FIX(MAP_EXECUTABLE));
|
2506
|
+
#endif
|
2507
|
+
#ifdef MAP_NORESERVE
|
2508
|
+
rb_define_const(mm_cMap, "MAP_NORESERVE", INT2FIX(MAP_NORESERVE));
|
2509
|
+
#endif
|
2510
|
+
#ifdef MAP_LOCKED
|
2511
|
+
rb_define_const(mm_cMap, "MAP_LOCKED", INT2FIX(MAP_LOCKED));
|
2512
|
+
#endif
|
2513
|
+
#ifdef MAP_GROWSDOWN
|
2514
|
+
rb_define_const(mm_cMap, "MAP_GROWSDOWN", INT2FIX(MAP_GROWSDOWN));
|
2515
|
+
#endif
|
2516
|
+
#ifdef MAP_ANON
|
2517
|
+
rb_define_const(mm_cMap, "MAP_ANON", INT2FIX(MAP_ANON));
|
2518
|
+
#endif
|
2519
|
+
#ifdef MAP_ANONYMOUS
|
2520
|
+
rb_define_const(mm_cMap, "MAP_ANONYMOUS", INT2FIX(MAP_ANONYMOUS));
|
2521
|
+
#endif
|
2522
|
+
#ifdef MAP_NOSYNC
|
2523
|
+
rb_define_const(mm_cMap, "MAP_NOSYNC", INT2FIX(MAP_NOSYNC));
|
2524
|
+
#endif
|
2525
|
+
#ifdef MCL_CURRENT
|
2526
|
+
rb_define_const(mm_cMap, "MCL_CURRENT", INT2FIX(MCL_CURRENT));
|
2527
|
+
rb_define_const(mm_cMap, "MCL_FUTURE", INT2FIX(MCL_FUTURE));
|
2528
|
+
#endif
|
2529
|
+
|
2530
|
+
rb_define_alloc_func(mm_cMap, mm_s_alloc);
|
2531
|
+
rb_define_singleton_method(mm_cMap, "new", mm_s_new, -1);
|
2532
|
+
rb_define_singleton_method(mm_cMap, "mlockall", mm_mlockall, 1);
|
2533
|
+
rb_define_singleton_method(mm_cMap, "lockall", mm_mlockall, 1);
|
2534
|
+
rb_define_singleton_method(mm_cMap, "munlockall", mm_munlockall, 0);
|
2535
|
+
rb_define_singleton_method(mm_cMap, "unlockall", mm_munlockall, 0);
|
2536
|
+
|
2537
|
+
rb_define_method(mm_cMap, "initialize", mm_init, -1);
|
2538
|
+
|
2539
|
+
rb_define_method(mm_cMap, "unmap", mm_unmap, 0);
|
2540
|
+
rb_define_method(mm_cMap, "munmap", mm_unmap, 0);
|
2541
|
+
rb_define_method(mm_cMap, "msync", mm_msync, -1);
|
2542
|
+
rb_define_method(mm_cMap, "sync", mm_msync, -1);
|
2543
|
+
rb_define_method(mm_cMap, "flush", mm_msync, -1);
|
2544
|
+
rb_define_method(mm_cMap, "mprotect", mm_mprotect, 1);
|
2545
|
+
rb_define_method(mm_cMap, "protect", mm_mprotect, 1);
|
2546
|
+
#ifdef MADV_NORMAL
|
2547
|
+
rb_define_method(mm_cMap, "madvise", mm_madvise, 1);
|
2548
|
+
rb_define_method(mm_cMap, "advise", mm_madvise, 1);
|
2549
|
+
#endif
|
2550
|
+
rb_define_method(mm_cMap, "mlock", mm_mlock, 0);
|
2551
|
+
rb_define_method(mm_cMap, "lock", mm_mlock, 0);
|
2552
|
+
rb_define_method(mm_cMap, "munlock", mm_munlock, 0);
|
2553
|
+
rb_define_method(mm_cMap, "unlock", mm_munlock, 0);
|
2554
|
+
|
2555
|
+
rb_define_method(mm_cMap, "extend", mm_extend, 1);
|
2556
|
+
rb_define_method(mm_cMap, "freeze", mm_freeze, 0);
|
2557
|
+
rb_define_method(mm_cMap, "<=>", mm_cmp, 1);
|
2558
|
+
rb_define_method(mm_cMap, "==", mm_equal, 1);
|
2559
|
+
rb_define_method(mm_cMap, "===", mm_equal, 1);
|
2560
|
+
rb_define_method(mm_cMap, "eql?", mm_eql, 1);
|
2561
|
+
rb_define_method(mm_cMap, "hash", mm_hash, 0);
|
2562
|
+
#if HAVE_RB_STR_CASECMP
|
2563
|
+
rb_define_method(mm_cMap, "casecmp", mm_casecmp, 1);
|
2564
|
+
#endif
|
2565
|
+
rb_define_method(mm_cMap, "[]", mm_aref_m, -1);
|
2566
|
+
rb_define_method(mm_cMap, "[]=", mm_aset_m, -1);
|
2567
|
+
#if HAVE_RB_STR_INSERT
|
2568
|
+
rb_define_method(mm_cMap, "insert", mm_insert, 2);
|
2569
|
+
#endif
|
2570
|
+
rb_define_method(mm_cMap, "length", mm_size, 0);
|
2571
|
+
rb_define_method(mm_cMap, "size", mm_size, 0);
|
2572
|
+
rb_define_method(mm_cMap, "empty?", mm_empty, 0);
|
2573
|
+
rb_define_method(mm_cMap, "=~", mm_match, 1);
|
2574
|
+
#if HAVE_RB_STR_MATCH
|
2575
|
+
rb_define_method(mm_cMap, "match", mm_match_m, 1);
|
2576
|
+
#endif
|
2577
|
+
rb_define_method(mm_cMap, "index", mm_index, -1);
|
2578
|
+
rb_define_method(mm_cMap, "rindex", mm_rindex, -1);
|
2579
|
+
|
2580
|
+
rb_define_method(mm_cMap, "to_str", mm_to_str, 0);
|
2581
|
+
|
2582
|
+
rb_define_method(mm_cMap, "upcase!", mm_upcase_bang, 0);
|
2583
|
+
rb_define_method(mm_cMap, "downcase!", mm_downcase_bang, 0);
|
2584
|
+
rb_define_method(mm_cMap, "capitalize!", mm_capitalize_bang, 0);
|
2585
|
+
rb_define_method(mm_cMap, "swapcase!", mm_swapcase_bang, 0);
|
2586
|
+
|
2587
|
+
rb_define_method(mm_cMap, "split", mm_split, -1);
|
2588
|
+
rb_define_method(mm_cMap, "reverse!", mm_reverse_bang, 0);
|
2589
|
+
rb_define_method(mm_cMap, "concat", mm_concat, 1);
|
2590
|
+
rb_define_method(mm_cMap, "<<", mm_concat, 1);
|
2591
|
+
rb_define_method(mm_cMap, "crypt", mm_crypt, 1);
|
2592
|
+
|
2593
|
+
rb_define_method(mm_cMap, "include?", mm_include, 1);
|
2594
|
+
|
2595
|
+
rb_define_method(mm_cMap, "scan", mm_scan, 1);
|
2596
|
+
|
2597
|
+
rb_define_method(mm_cMap, "sub!", mm_sub_bang, -1);
|
2598
|
+
rb_define_method(mm_cMap, "gsub!", mm_gsub_bang, -1);
|
2599
|
+
rb_define_method(mm_cMap, "strip!", mm_strip_bang, 0);
|
2600
|
+
#if HAVE_RB_STR_LSTRIP
|
2601
|
+
rb_define_method(mm_cMap, "lstrip!", mm_lstrip_bang, 0);
|
2602
|
+
rb_define_method(mm_cMap, "rstrip!", mm_rstrip_bang, 0);
|
2603
|
+
#endif
|
2604
|
+
rb_define_method(mm_cMap, "chop!", mm_chop_bang, 0);
|
2605
|
+
rb_define_method(mm_cMap, "chomp!", mm_chomp_bang, -1);
|
2606
|
+
|
2607
|
+
rb_define_method(mm_cMap, "count", mm_count, -1);
|
2608
|
+
|
2609
|
+
rb_define_method(mm_cMap, "tr!", mm_tr_bang, 2);
|
2610
|
+
rb_define_method(mm_cMap, "tr_s!", mm_tr_s_bang, 2);
|
2611
|
+
rb_define_method(mm_cMap, "delete!", mm_delete_bang, -1);
|
2612
|
+
rb_define_method(mm_cMap, "squeeze!", mm_squeeze_bang, -1);
|
2613
|
+
|
2614
|
+
rb_define_method(mm_cMap, "each_line", mm_each_line, -1);
|
2615
|
+
rb_define_method(mm_cMap, "each", mm_each_line, -1);
|
2616
|
+
rb_define_method(mm_cMap, "each_byte", mm_each_byte, -1);
|
2617
|
+
|
2618
|
+
rb_define_method(mm_cMap, "sum", mm_sum, -1);
|
2619
|
+
|
2620
|
+
rb_define_method(mm_cMap, "slice", mm_aref_m, -1);
|
2621
|
+
rb_define_method(mm_cMap, "slice!", mm_slice_bang, -1);
|
2622
|
+
rb_define_method(mm_cMap, "semlock", mm_semlock, -1);
|
2623
|
+
rb_define_method(mm_cMap, "ipc_key", mm_ipc_key, 0);
|
2624
|
+
}
|