summaryrefslogtreecommitdiffstats
path: root/mmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mmap.c')
-rw-r--r--mmap.c162
1 files changed, 118 insertions, 44 deletions
diff --git a/mmap.c b/mmap.c
index 37d400b..5d33fba 100644
--- a/mmap.c
+++ b/mmap.c
@@ -53,6 +53,8 @@ mm_free(t_mm)
if (t_mm->path != (char *)-1) {
if (t_mm->real < t_mm->len && t_mm->vscope != MAP_PRIVATE &&
truncate(t_mm->path, t_mm->real) == -1) {
+ free(t_mm->path);
+ free(t_mm);
rb_raise(rb_eTypeError, "truncate");
}
free(t_mm->path);
@@ -118,19 +120,28 @@ mm_str(obj, modify)
VALUE ret;
GetMmap(obj, t_mm, modify & ~MM_ORIGIN);
+#if RUBY_VERSION_CODE >= 171
+ ret = rb_obj_alloc(rb_cString);
+ if (rb_obj_tainted(obj)) {
+ OBJ_TAINT(ret);
+ }
+#else
if (rb_obj_tainted(obj)) {
ret = rb_tainted_str_new2("");
}
else {
ret = rb_str_new2("");
}
+#endif
if (modify & MM_MODIFY) {
if (t_mm->frozen & MM_FROZEN) rb_error_frozen("mmap");
if (!OBJ_TAINTED(ret) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify mmap");
}
if (t_mm->frozen & MM_FROZEN) ret = rb_obj_freeze(ret);
+#if RUBY_VERSION_CODE < 171
free(RSTRING(ret)->ptr);
+#endif
RSTRING(ret)->ptr = t_mm->addr;
RSTRING(ret)->len = t_mm->real;
if (modify & MM_ORIGIN)
@@ -181,7 +192,7 @@ mm_i_options(arg, obj)
}
static VALUE
-mm_map(argc, argv, obj)
+mm_s_new(argc, argv, obj)
VALUE obj, *argv;
int argc;
{
@@ -406,7 +417,7 @@ mm_mprotect(obj, a)
if ((pmode & PROT_WRITE) && (t_mm->frozen & MM_FROZEN))
rb_error_frozen("mmap");
if ((ret = mprotect(t_mm->addr, t_mm->len, pmode)) != 0) {
- rb_raise(rb_eArgError, "msync(%d)", ret);
+ rb_raise(rb_eArgError, "mprotect(%d)", ret);
}
t_mm->pmode = pmode;
if (pmode & PROT_READ) {
@@ -439,22 +450,20 @@ mm_madvise(obj, a)
return Qnil;
}
-#define StringMmap(b, bp, bl) \
- do { \
- if (TYPE(b) == T_DATA && rb_obj_is_kind_of(b, mm_cMap)) { \
- mm_mmap *b_mm; \
- \
- GetMmap(b, b_mm, 0); \
- bp = b_mm->addr; \
- bl = b_mm->real; \
- } \
- else { \
- if (TYPE(b) != T_STRING) b = rb_str_to_str(b); \
- bp = RSTRING(b)->ptr; \
- bl = RSTRING(b)->len; \
- } \
- } while (0);
-
+#define StringMmap(b, bp, bl) \
+do { \
+ if (TYPE(b) == T_DATA && RDATA(b)->dfree == (RUBY_DATA_FUNC)mm_free) { \
+ mm_mmap *b_mm; \
+ GetMmap(b, b_mm, 0); \
+ bp = b_mm->addr; \
+ bl = b_mm->real; \
+ } \
+ else { \
+ if (TYPE(b) != T_STRING) b = rb_str_to_str(b); \
+ bp = RSTRING(b)->ptr; \
+ bl = RSTRING(b)->len; \
+ } \
+} while (0);
static void
mm_update(str, beg, len, val)
@@ -512,7 +521,7 @@ mm_match(x, y)
long start;
x = mm_str(x, MM_ORIGIN);
- if (TYPE(y) == T_DATA && rb_obj_is_kind_of(y, mm_cMap)) {
+ if (TYPE(y) == T_DATA && RDATA(y)->dfree == (RUBY_DATA_FUNC)mm_free) {
y = mm_to_str(y);
}
switch (TYPE(y)) {
@@ -592,7 +601,7 @@ mm_sub_bang(argc, argv, obj)
iter = 1;
}
else if (argc == 2) {
- repl = rb_obj_as_string(argv[1]);;
+ repl = rb_str_to_str(argv[1]);
if (OBJ_TAINTED(repl)) tainted = 1;
}
else {
@@ -634,7 +643,7 @@ mm_sub_bang(argc, argv, obj)
}
memcpy(RSTRING(str)->ptr + start,
RSTRING(repl)->ptr, RSTRING(repl)->len);
- RSTRING(str)->len += RSTRING(repl)->len - plen;
+ t_mm->real += RSTRING(repl)->len - plen;
if (tainted) OBJ_TAINT(obj);
res = obj;
@@ -661,7 +670,7 @@ mm_gsub_bang(argc, argv, obj)
iter = 1;
}
else if (argc == 2) {
- repl = rb_obj_as_string(argv[1]);
+ repl = rb_str_to_str(argv[1]);
if (OBJ_TAINTED(repl)) tainted = 1;
}
else {
@@ -727,6 +736,39 @@ mm_gsub_bang(argc, argv, obj)
static VALUE mm_index __((int, VALUE *, VALUE));
+#if RUBY_VERSION_CODE >= 171
+
+static VALUE
+mm_subpat_set(obj, re, offset, val)
+ VALUE obj, re;
+ int offset;
+ VALUE val;
+{
+ VALUE str, match;
+ int start, end, len;
+ mm_mmap *t_mm;
+
+ str = mm_str(obj, MM_MODIFY | MM_ORIGIN);
+ if (rb_reg_search(re, str, 0, 0) < 0) {
+ rb_raise(rb_eIndexError, "regexp not matched");
+ }
+ match = rb_backref_get();
+ if (offset >= RMATCH(match)->regs->num_regs) {
+ rb_raise(rb_eIndexError, "index %d out of regexp", offset);
+ }
+
+ start = RMATCH(match)->BEG(offset);
+ if (start == -1) {
+ rb_raise(rb_eIndexError, "regexp group %d not matched", offset);
+ }
+ end = RMATCH(match)->END(offset);
+ len = end - start;
+ GetMmap(str, t_mm, MM_MODIFY);
+ mm_update(t_mm, start, len, val);
+}
+
+#endif
+
static VALUE
mm_aset(str, indx, val)
VALUE str;
@@ -759,18 +801,22 @@ mm_aset(str, indx, val)
return val;
case T_REGEXP:
+#if RUBY_VERSION_CODE >= 171
+ mm_subpat_set(str, 0, indx, val);
+#else
{
VALUE args[2];
args[0] = indx;
args[1] = val;
mm_sub_bang(2, args, str);
}
+#endif
return val;
case T_STRING:
beg = mm_index(1, &indx, str);
if (beg != -1) {
- mm_update(str, beg, RSTRING(indx)->len, val);
+ mm_update(t_mm, beg, RSTRING(indx)->len, val);
}
return val;
@@ -800,10 +846,17 @@ mm_aset_m(argc, argv, str)
if (argc == 3) {
long beg, len;
- if (TYPE(argv[2]) != T_STRING) argv[2] = rb_str_to_str(argv[2]);
- beg = NUM2INT(argv[0]);
- len = NUM2INT(argv[1]);
- mm_update(t_mm, beg, len, argv[2]);
+#if RUBY_VERSION_CODE >= 171
+ if (TYPE(argv[0]) == T_REGEXP) {
+ mm_subpat_set(str, argv[0], NUM2INT(argv[1]), argv[2]);
+ }
+ else
+#endif
+ {
+ beg = NUM2INT(argv[0]);
+ len = NUM2INT(argv[1]);
+ mm_update(t_mm, beg, len, argv[2]);
+ }
return argv[2];
}
if (argc != 2) {
@@ -997,7 +1050,7 @@ mm_strip_bang(str)
VALUE str;
{
VALUE l = mm_lstrip_bang(str);
- VALUE r = mm_str_rstrip_bang(str);
+ VALUE r = mm_rstrip_bang(str);
if (NIL_P(l) && NIL_P(r)) return Qnil;
return str;
@@ -1005,16 +1058,16 @@ mm_strip_bang(str)
#endif
-#define MmapStr(b, recycle) \
-do { \
- recycle = 0; \
- if (TYPE(b) == T_DATA && rb_obj_is_kind_of(b, mm_cMap) == Qtrue) { \
- recycle = 1; \
- b = mm_str(b, MM_ORIGIN); \
- } \
- else { \
- b = rb_str_to_str(b); \
- } \
+#define MmapStr(b, recycle) \
+do { \
+ recycle = 0; \
+ if (TYPE(b) == T_DATA && RDATA(b)->dfree == (RUBY_DATA_FUNC)mm_free) { \
+ recycle = 1; \
+ b = mm_str(b, MM_ORIGIN); \
+ } \
+ else { \
+ b = rb_str_to_str(b); \
+ } \
} while (0);
@@ -1057,13 +1110,34 @@ mm_equal(a, b)
VALUE a, b;
{
VALUE result;
- int recycle = 0;
+ if (a == b) return Qtrue;
+ if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RUBY_DATA_FUNC)mm_free)
+ return Qfalse;
+
a = mm_str(a, MM_ORIGIN);
- MmapStr(b, recycle);
+ b = mm_str(b, MM_ORIGIN);
result = rb_funcall2(a, rb_intern("=="), 1, &b);
rb_gc_force_recycle(a);
- if (recycle) rb_gc_force_recycle(b);
+ rb_gc_force_recycle(b);
+ return result;
+}
+
+static VALUE
+mm_eql(a, b)
+ VALUE a, b;
+{
+ VALUE result;
+
+ if (a == b) return Qtrue;
+ if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RUBY_DATA_FUNC)mm_free)
+ return Qfalse;
+
+ a = mm_str(a, MM_ORIGIN);
+ b = mm_str(b, MM_ORIGIN);
+ result = rb_funcall2(a, rb_intern("eql?"), 1, &b);
+ rb_gc_force_recycle(a);
+ rb_gc_force_recycle(b);
return result;
}
@@ -1468,7 +1542,7 @@ Init_mmap()
rb_include_module(mm_cMap, rb_mComparable);
rb_include_module(mm_cMap, rb_mEnumerable);
- rb_define_singleton_method(mm_cMap, "new", mm_map, -1);
+ rb_define_singleton_method(mm_cMap, "new", mm_s_new, -1);
rb_define_singleton_method(mm_cMap, "mlockall", mm_mlockall, 1);
rb_define_singleton_method(mm_cMap, "lockall", mm_mlockall, 1);
rb_define_singleton_method(mm_cMap, "munlockall", mm_munlockall, 0);
@@ -1495,7 +1569,7 @@ Init_mmap()
rb_define_method(mm_cMap, "<=>", mm_cmp, 1);
rb_define_method(mm_cMap, "==", mm_equal, 1);
rb_define_method(mm_cMap, "===", mm_equal, 1);
- rb_define_method(mm_cMap, "eql?", mm_equal, 1);
+ rb_define_method(mm_cMap, "eql?", mm_eql, 1);
rb_define_method(mm_cMap, "hash", mm_hash, 0);
#if RUBY_VERSION_CODE >= 171
rb_define_method(mm_cMap, "casecmp", mm_casecmp, 1);
@@ -1524,7 +1598,7 @@ Init_mmap()
rb_define_method(mm_cMap, "to_i", mm_undefined, -1);
rb_define_method(mm_cMap, "to_f", mm_undefined, -1);
- rb_define_method(mm_cMap, "to_s", mm_undefined, 0);
+ rb_define_method(mm_cMap, "to_s", rb_any_to_s, 0);
rb_define_method(mm_cMap, "to_str", mm_to_str, 0);
rb_define_method(mm_cMap, "inspect", mm_inspect, 0);
rb_define_method(mm_cMap, "dump", mm_undefined, -1);