mmapscanner 0.1a → 0.2

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.
Files changed (4) hide show
  1. data/README.md +2 -0
  2. data/ext/mmapscanner.c +102 -101
  3. data/spec/mmapscanner_spec.rb +148 -122
  4. metadata +5 -5
data/README.md CHANGED
@@ -38,6 +38,8 @@ Usage
38
38
  # ファイルの先頭 4096 バイト以降の 1234 バイト分を mmap
39
39
  ms = MmapScanner.new(File.open("filename"), 4096, 1234)
40
40
 
41
+ * MmapScanner.new は文字列も受け付けます。文字列が途中で変更された時の動作は不定です。
42
+
41
43
  * size, length は mmap(2) したサイズを返します。
42
44
  * to_s は mmap(2) した領域を String で返します。Encoding は常に ASCII-8BIT です。
43
45
  * slice は mmap(2) した領域の一部を新たな MmapScanner オブジェクトで返します。
data/ext/mmapscanner.c CHANGED
@@ -6,11 +6,11 @@
6
6
  #include <ruby/io.h>
7
7
 
8
8
  static VALUE cMmapScanner;
9
+ static VALUE cMmap;
9
10
 
10
11
  typedef struct {
11
12
  char *ptr;
12
13
  size_t size;
13
- size_t pos;
14
14
  } mmap_data_t;
15
15
 
16
16
  static void mmap_free(mmap_data_t *data)
@@ -20,144 +20,148 @@ static void mmap_free(mmap_data_t *data)
20
20
  free(data);
21
21
  }
22
22
 
23
- static VALUE allocate(VALUE klass)
23
+ static VALUE create_mmap_object(int fd, size_t offset, size_t size)
24
24
  {
25
- VALUE obj;
26
25
  mmap_data_t *data;
27
-
26
+ void *ptr;
27
+ if ((ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, offset)) == MAP_FAILED) {
28
+ rb_exc_raise(rb_funcall(rb_eSystemCallError, rb_intern("new"), 1, INT2FIX(errno)));
29
+ }
28
30
  data = xmalloc(sizeof(mmap_data_t));
29
- data->ptr = NULL;
30
- data->size = 0;
31
- data->pos = 0;
32
- obj = Data_Wrap_Struct(klass, 0, mmap_free, data);
33
- rb_iv_set(obj, "parent", Qnil);
34
- return obj;
31
+ data->ptr = ptr;
32
+ data->size = size;
33
+ return Data_Wrap_Struct(cMmap, 0, mmap_free, data);
35
34
  }
36
35
 
37
36
  static VALUE initialize(int argc, VALUE *argv, VALUE obj)
38
37
  {
39
- VALUE src, size, pos, p, pp;
40
- int fd;
41
- void *ptr;
42
- mmap_data_t *data, *parent;
43
- struct stat st;
44
- size_t sz, offset;
45
-
46
- Data_Get_Struct(obj, mmap_data_t, data);
47
- if (data->ptr)
48
- rb_raise(rb_eRuntimeError, "already initialized");
49
- rb_scan_args(argc, argv, "12", &src, &pos, &size);
50
- if (pos != Qnil && NUM2LL(pos) < 0)
51
- rb_raise(rb_eRangeError, "position out of range: %lld", NUM2LL(pos));
52
- if (size != Qnil && NUM2LL(size) < 0)
53
- rb_raise(rb_eRangeError, "length out of range: %lld", NUM2LL(size));
54
- offset = pos == Qnil ? 0 : NUM2SIZET(pos);
38
+ VALUE src, voffset, vsize;
39
+ size_t offset, size;
40
+ size_t src_offset, src_size;
41
+ VALUE src_data;
42
+
43
+ rb_scan_args(argc, argv, "12", &src, &voffset, &vsize);
44
+ if (voffset != Qnil && NUM2LL(voffset) < 0)
45
+ rb_raise(rb_eRangeError, "offset out of range: %lld", NUM2LL(voffset));
46
+ if (vsize != Qnil && NUM2LL(vsize) < 0)
47
+ rb_raise(rb_eRangeError, "length out of range: %lld", NUM2LL(vsize));
48
+ offset = voffset == Qnil ? 0 : NUM2SIZET(voffset);
55
49
  if (rb_obj_class(src) == cMmapScanner) {
56
- Data_Get_Struct(src, mmap_data_t, parent);
57
- if (offset >= parent->size)
58
- rb_raise(rb_eRangeError, "length out of range: %zu >= %zu", offset, parent->size);
59
- sz = size == Qnil ? parent->size - offset : NUM2SIZET(size);
60
- ptr = parent->ptr + offset;
61
- if (sz > parent->size - offset)
62
- sz = parent->size-offset;
63
- data->ptr = ptr;
64
- data->size = sz;
65
- p = src;
66
- while ((pp = rb_iv_get(p, "parent")) != Qnil)
67
- p = pp;
68
- rb_iv_set(obj, "parent", p);
69
- return;
50
+ src_offset = NUM2SIZET(rb_iv_get(src, "offset"));
51
+ src_size = NUM2SIZET(rb_iv_get(src, "size"));
52
+ src_data = rb_iv_get(src, "data");
53
+ } else if (TYPE(src) == T_FILE) {
54
+ int fd;
55
+ struct stat st;
56
+ fd = RFILE(src)->fptr->fd;
57
+ fstat(fd, &st);
58
+ src_offset = 0;
59
+ src_size = st.st_size;
60
+ size = vsize == Qnil ? src_size - offset : NUM2SIZET(vsize);
61
+ if (size > st.st_size - offset)
62
+ size = st.st_size - offset;
63
+ src_data = create_mmap_object(fd, offset, size);
64
+ } else if (TYPE(src) == T_STRING) {
65
+ src_offset = 0;
66
+ src_size = RSTRING_LEN(src);
67
+ src_data = src;
68
+ } else {
69
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected File/String/MmapScanner)", rb_obj_classname(src));
70
70
  }
71
- Check_Type(src, T_FILE);
72
- fd = RFILE(src)->fptr->fd;
73
- fstat(fd, &st);
74
- sz = size == Qnil ? st.st_size - offset : NUM2SIZET(size);
75
- if (sz > st.st_size - offset)
76
- sz = st.st_size - offset;
77
- if ((ptr = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, offset)) == MAP_FAILED) {
78
- rb_exc_raise(rb_funcall(rb_eSystemCallError, rb_intern("new"), 1, INT2FIX(errno)));
79
- }
80
- data->ptr = ptr;
81
- data->size = sz;
71
+ if (offset >= src_size)
72
+ rb_raise(rb_eRangeError, "length out of range: %zu >= %zu", offset, src_size);
73
+ size = vsize == Qnil ? src_size - offset : NUM2SIZET(vsize);
74
+ if (size > src_size - offset)
75
+ size = src_size - offset;
76
+ rb_iv_set(obj, "offset", SIZET2NUM(src_offset + offset));
77
+ rb_iv_set(obj, "size", SIZET2NUM(size));
78
+ rb_iv_set(obj, "data", src_data);
79
+ rb_iv_set(obj, "pos", INT2NUM(0));
80
+ return Qnil;
82
81
  }
83
82
 
84
83
  static VALUE size(VALUE obj)
85
84
  {
86
- mmap_data_t *data;
87
-
88
- Data_Get_Struct(obj, mmap_data_t, data);
89
- return ULL2NUM(data->size);
85
+ return rb_iv_get(obj, "size");
90
86
  }
91
87
 
92
88
  static VALUE to_s(VALUE obj)
93
89
  {
94
- mmap_data_t *data;
90
+ size_t offset = NUM2SIZET(rb_iv_get(obj, "offset"));
91
+ size_t size = NUM2SIZET(rb_iv_get(obj, "size"));
92
+ VALUE data = rb_iv_get(obj, "data");
93
+ mmap_data_t *mdata;
95
94
 
96
- Data_Get_Struct(obj, mmap_data_t, data);
97
- return rb_str_new(data->ptr, data->size);
95
+ if (TYPE(data) == T_STRING)
96
+ return rb_str_new(RSTRING_PTR(data)+offset, size);
97
+ Data_Get_Struct(data, mmap_data_t, mdata);
98
+ return rb_str_new(mdata->ptr+offset, size);
98
99
  }
99
100
 
100
101
  static VALUE slice(VALUE obj, VALUE pos, VALUE len)
101
102
  {
102
- size_t offset;
103
- size_t length;
104
- mmap_data_t *data;
105
-
106
- Data_Get_Struct(obj, mmap_data_t, data);
107
103
  return rb_funcall(cMmapScanner, rb_intern("new"), 3, obj, pos, len);
108
104
  }
109
105
 
110
106
  static VALUE inspect(VALUE obj)
111
107
  {
112
- rb_str_new2("#<MmapScanner>");
108
+ return rb_str_new2("#<MmapScanner>");
113
109
  }
114
110
 
115
111
  static VALUE pos(VALUE obj)
116
112
  {
117
- mmap_data_t *data;
118
-
119
- Data_Get_Struct(obj, mmap_data_t, data);
120
- return ULL2NUM(data->pos);
113
+ return rb_iv_get(obj, "pos");
121
114
  }
122
115
 
123
116
  static VALUE set_pos(VALUE obj, VALUE pos)
124
117
  {
125
- mmap_data_t *data;
126
- size_t p;
118
+ size_t p, size;
127
119
 
128
120
  if (NUM2LL(pos) < 0)
129
121
  rb_raise(rb_eRangeError, "out of range: %lld", NUM2LL(pos));
130
- Data_Get_Struct(obj, mmap_data_t, data);
131
122
  p = NUM2SIZET(pos);
132
- if (p > data->size)
133
- rb_raise(rb_eRangeError, "out of range: %zu > %zu", p, data->size);
134
- data->pos = p;
123
+ size = NUM2SIZET(rb_iv_get(obj, "size"));
124
+ if (p > size)
125
+ rb_raise(rb_eRangeError, "out of range: %zu > %zu", p, size);
126
+ rb_iv_set(obj, "pos", pos);
135
127
  return pos;
136
128
  }
137
129
 
138
130
  static VALUE scan_sub(VALUE obj, VALUE re, int forward)
139
131
  {
140
132
  regex_t *rb_reg_prepare_re(VALUE re, VALUE str);
141
- mmap_data_t *data;
142
133
  regex_t *reg;
143
134
  int tmpreg;
144
135
  int result;
145
136
  struct re_registers regs;
146
137
  size_t old_pos, matched_len;
138
+ char *ptr;
139
+ size_t pos, size;
140
+ VALUE data;
141
+ mmap_data_t *mdata;
147
142
 
148
143
  Check_Type(re, T_REGEXP);
149
- Data_Get_Struct(obj, mmap_data_t, data);
150
- if (data->pos >= data->size)
144
+ pos = NUM2SIZET(rb_iv_get(obj, "pos"));
145
+ size = NUM2SIZET(rb_iv_get(obj, "size"));
146
+ if (pos >= size)
151
147
  return Qnil;
148
+ data = rb_iv_get(obj, "data");
149
+ if (TYPE(data) == T_STRING)
150
+ ptr = RSTRING_PTR(data);
151
+ else {
152
+ Data_Get_Struct(data, mmap_data_t, mdata);
153
+ ptr = mdata->ptr;
154
+ }
155
+ ptr += NUM2SIZET(rb_iv_get(obj, "offset"));
152
156
 
153
157
  reg = rb_reg_prepare_re(re, rb_str_new("", 0));
154
158
  tmpreg = reg != RREGEXP(re)->ptr;
155
159
  if (!tmpreg) RREGEXP(re)->usecnt++;
156
160
 
157
161
  onig_region_init(&regs);
158
- result = onig_match(reg, (UChar* )(data->ptr+data->pos),
159
- (UChar* )(data->ptr+data->size),
160
- (UChar* )(data->ptr+data->pos),
162
+ result = onig_match(reg, (UChar* )(ptr+pos),
163
+ (UChar* )(ptr+size),
164
+ (UChar* )(ptr+pos),
161
165
  &regs, ONIG_OPTION_NONE);
162
166
  if (!tmpreg) RREGEXP(re)->usecnt--;
163
167
  if (tmpreg) {
@@ -170,10 +174,12 @@ static VALUE scan_sub(VALUE obj, VALUE re, int forward)
170
174
  }
171
175
  if (result < 0)
172
176
  return Qnil;
173
- old_pos = data->pos;
177
+ old_pos = pos;
174
178
  matched_len = regs.end[0];
175
- if (forward)
176
- data->pos += matched_len;
179
+ if (forward) {
180
+ pos += matched_len;
181
+ rb_iv_set(obj, "pos", SIZET2NUM(pos));
182
+ }
177
183
  return rb_funcall(cMmapScanner, rb_intern("new"), 3, obj, ULL2NUM(old_pos), ULL2NUM(matched_len));
178
184
  }
179
185
 
@@ -189,52 +195,45 @@ static VALUE check(VALUE obj, VALUE re)
189
195
 
190
196
  static VALUE skip(VALUE obj, VALUE re)
191
197
  {
192
- mmap_data_t *data;
193
198
  VALUE ret = scan_sub(obj, re, 1);
194
199
  if (ret == Qnil)
195
200
  return ret;
196
- Data_Get_Struct(ret, mmap_data_t, data);
197
- return ULL2NUM(data->size);
201
+ return rb_iv_get(ret, "size");
198
202
  }
199
203
 
200
204
  static VALUE match_p(VALUE obj, VALUE re)
201
205
  {
202
- mmap_data_t *data;
203
206
  VALUE ret = scan_sub(obj, re, 0);
204
207
  if (ret == Qnil)
205
208
  return ret;
206
- Data_Get_Struct(ret, mmap_data_t, data);
207
- return ULL2NUM(data->size);
209
+ return rb_iv_get(ret, "size");
208
210
  }
209
211
 
210
212
  static VALUE peek(VALUE obj, VALUE size)
211
213
  {
212
214
  size_t sz = NUM2SIZET(size);
213
- mmap_data_t *data;
214
- Data_Get_Struct(obj, mmap_data_t, data);
215
- if (sz > data->size - data->pos)
216
- sz = data->size - data->pos;
217
- return rb_funcall(cMmapScanner, rb_intern("new"), 3, obj, SIZET2NUM(data->pos), SIZET2NUM(sz));
215
+ size_t data_pos = NUM2SIZET(rb_iv_get(obj, "pos"));
216
+ size_t data_size = NUM2SIZET(rb_iv_get(obj, "size"));
217
+ if (sz > data_size - data_pos)
218
+ sz = data_size - data_pos;
219
+ return rb_funcall(cMmapScanner, rb_intern("new"), 3, obj, SIZET2NUM(data_pos), SIZET2NUM(sz));
218
220
  }
219
221
 
220
222
  static VALUE eos_p(VALUE obj)
221
223
  {
222
- mmap_data_t *data;
223
- Data_Get_Struct(obj, mmap_data_t, data);
224
- return data->pos >= data->size ? Qtrue : Qfalse;
224
+ size_t data_pos = NUM2SIZET(rb_iv_get(obj, "pos"));
225
+ size_t data_size = NUM2SIZET(rb_iv_get(obj, "size"));
226
+ return data_pos >= data_size ? Qtrue : Qfalse;
225
227
  }
226
228
 
227
229
  static VALUE rest(VALUE obj)
228
230
  {
229
- mmap_data_t *data;
230
- Data_Get_Struct(obj, mmap_data_t, data);
231
- return rb_funcall(cMmapScanner, rb_intern("new"), 2, obj, SIZET2NUM(data->pos));
231
+ return rb_funcall(cMmapScanner, rb_intern("new"), 2, obj, rb_iv_get(obj, "pos"));
232
232
  }
233
233
 
234
234
  void Init_mmapscanner(void)
235
235
  {
236
236
  cMmapScanner = rb_define_class("MmapScanner", rb_cObject);
237
- rb_define_alloc_func(cMmapScanner, allocate);
238
237
  rb_define_method(cMmapScanner, "initialize", initialize, -1);
239
238
  rb_define_method(cMmapScanner, "size", size, 0);
240
239
  rb_define_method(cMmapScanner, "length", size, 0);
@@ -251,4 +250,6 @@ void Init_mmapscanner(void)
251
250
  rb_define_method(cMmapScanner, "peek", peek, 1);
252
251
  rb_define_method(cMmapScanner, "eos?", eos_p, 0);
253
252
  rb_define_method(cMmapScanner, "rest", rest, 0);
253
+
254
+ cMmap = rb_define_class_under(cMmapScanner, "Mmap", rb_cObject);
254
255
  }
@@ -4,138 +4,164 @@ $LOAD_PATH.unshift "#{File.dirname __FILE__}/../ext"
4
4
  require 'mmapscanner'
5
5
 
6
6
  describe MmapScanner do
7
- before do
8
- tmpf = Tempfile.new 'mmapscanner'
9
- tmpf.write '0123456789'*1000
10
- @file = File.open(tmpf.path)
11
- end
12
- subject{MmapScanner.new(@file)}
13
- it '#size returns size of file' do
14
- subject.size.should == 10000
15
- end
16
- it '#to_s returns contents of file' do
17
- subject.to_s.should == '0123456789'*1000
18
- end
19
- describe '#slice' do
20
- it 'returns MmapScanner' do
21
- subject.slice(10, 100).should be_instance_of MmapScanner
22
- end
23
- end
24
- it '#inspect returns "#<MmapScanner>"' do
25
- subject.inspect.should == '#<MmapScanner>'
26
- end
27
- it '#pos returns current position' do
28
- subject.pos.should == 0
29
- subject.scan(/.../)
30
- subject.pos.should == 3
31
- end
32
- describe '#pos=' do
33
- it 'change current position' do
34
- subject.pos = 100
35
- subject.pos.should == 100
36
- end
37
- it 'raise error when negative value' do
38
- expect{subject.pos = -1}.to raise_error(RangeError, 'out of range: -1')
39
- end
40
- it 'raise error when over size' do
41
- expect{subject.pos = 10001}.to raise_error(RangeError, 'out of range: 10001 > 10000')
42
- expect{subject.pos = 20000}.to raise_error(RangeError, 'out of range: 20000 > 10000')
7
+ shared_examples_for 'MmapScanner' do
8
+ it '#size returns size of file' do
9
+ subject.size.should == 10000
43
10
  end
44
- end
45
- describe '#scan' do
46
- it 'returns matched data as MmapScanner' do
47
- ret = subject.scan(/\d{10}/)
48
- ret.class.should == MmapScanner
49
- ret.to_s.should == '0123456789'
50
- end
51
- it 'returns nil if not matched' do
52
- subject.scan(/123/).should be_nil
11
+ it '#to_s returns contents of file' do
12
+ subject.to_s.should == '0123456789'*1000
53
13
  end
54
- it 'forward current position' do
55
- subject.scan(/\d{10}/)
56
- subject.pos.should == 10
14
+ describe '#slice' do
15
+ it 'returns MmapScanner' do
16
+ subject.slice(10, 100).should be_instance_of MmapScanner
17
+ end
57
18
  end
58
- end
59
- describe '#check' do
60
- it 'returns matched data as MmapScanner' do
61
- ret = subject.check(/\d{10}/)
62
- ret.class.should == MmapScanner
63
- ret.to_s.should == '0123456789'
19
+ it '#inspect returns "#<MmapScanner>"' do
20
+ subject.inspect.should == '#<MmapScanner>'
64
21
  end
65
- it 'returns nil if not matched' do
66
- subject.check(/123/).should be_nil
67
- end
68
- it 'do not forward current position' do
69
- ret = subject.check(/\d{10}/)
22
+ it '#pos returns current position' do
70
23
  subject.pos.should == 0
24
+ subject.scan(/.../)
25
+ subject.pos.should == 3
26
+ end
27
+ describe '#pos=' do
28
+ it 'change current position' do
29
+ subject.pos = 100
30
+ subject.pos.should == 100
31
+ end
32
+ it 'raise error when negative value' do
33
+ expect{subject.pos = -1}.to raise_error(RangeError, 'out of range: -1')
34
+ end
35
+ it 'raise error when over size' do
36
+ expect{subject.pos = 10001}.to raise_error(RangeError, 'out of range: 10001 > 10000')
37
+ expect{subject.pos = 20000}.to raise_error(RangeError, 'out of range: 20000 > 10000')
38
+ end
39
+ end
40
+ describe '#scan' do
41
+ it 'returns matched data as MmapScanner' do
42
+ ret = subject.scan(/\d{10}/)
43
+ ret.class.should == MmapScanner
44
+ ret.to_s.should == '0123456789'
45
+ end
46
+ it 'returns nil if not matched' do
47
+ subject.scan(/123/).should be_nil
48
+ end
49
+ it 'forward current position' do
50
+ subject.scan(/\d{10}/)
51
+ subject.pos.should == 10
52
+ end
53
+ end
54
+ describe '#check' do
55
+ it 'returns matched data as MmapScanner' do
56
+ ret = subject.check(/\d{10}/)
57
+ ret.class.should == MmapScanner
58
+ ret.to_s.should == '0123456789'
59
+ end
60
+ it 'returns nil if not matched' do
61
+ subject.check(/123/).should be_nil
62
+ end
63
+ it 'do not forward current position' do
64
+ ret = subject.check(/\d{10}/)
65
+ subject.pos.should == 0
66
+ end
67
+ end
68
+ describe '#skip' do
69
+ it 'returns length of matched data' do
70
+ subject.skip(/\d{10}/).should == 10
71
+ end
72
+ it 'returns nil if not matched' do
73
+ subject.skip(/123/).should be_nil
74
+ end
75
+ it 'forward current position' do
76
+ subject.skip(/\d{10}/)
77
+ subject.pos.should == 10
78
+ end
79
+ end
80
+ describe '#match?' do
81
+ it 'returns length of matched data' do
82
+ subject.match?(/\d{10}/).should == 10
83
+ end
84
+ it 'returns nil if not matched' do
85
+ subject.match?(/123/).should be_nil
86
+ end
87
+ it 'do not forward current position' do
88
+ subject.match?(/\d{10}/)
89
+ subject.pos.should == 0
90
+ end
91
+ end
92
+ describe '#peek' do
93
+ it 'returns MmapScanner' do
94
+ subject.peek(10).should be_instance_of MmapScanner
95
+ end
96
+ it 'do not forward current position' do
97
+ subject.peek(10)
98
+ subject.pos.should == 0
99
+ end
100
+ end
101
+ describe '#eos?' do
102
+ it 'returns true if eos' do
103
+ subject.pos = 10000
104
+ subject.eos?.should == true
105
+ end
106
+ it 'returns false if not eos' do
107
+ subject.pos = 9999
108
+ subject.eos?.should == false
109
+ end
110
+ end
111
+ describe '#rest' do
112
+ it 'returns rest data as MmapScanner' do
113
+ subject.pos = 9997
114
+ ret = subject.rest
115
+ ret.should be_instance_of MmapScanner
116
+ ret.to_s.should == '789'
117
+ end
118
+ end
119
+ describe '.new with position' do
120
+ it '#size is length of rest data' do
121
+ MmapScanner.new(src, 4096).size.should == src.size-4096
122
+ end
123
+ end
124
+ describe '.new with length' do
125
+ subject{MmapScanner.new(src, nil, 10)}
126
+ it '#size is specified size' do
127
+ subject.size.should == 10
128
+ end
129
+ it 'raise error when negative' do
130
+ expect{MmapScanner.new(src, nil, -1)}.to raise_error(RangeError, 'length out of range: -1')
131
+ end
71
132
  end
72
133
  end
73
- describe '#skip' do
74
- it 'returns length of matched data' do
75
- subject.skip(/\d{10}/).should == 10
76
- end
77
- it 'returns nil if not matched' do
78
- subject.skip(/123/).should be_nil
79
- end
80
- it 'forward current position' do
81
- subject.skip(/\d{10}/)
82
- subject.pos.should == 10
83
- end
84
- end
85
- describe '#match?' do
86
- it 'returns length of matched data' do
87
- subject.match?(/\d{10}/).should == 10
88
- end
89
- it 'returns nil if not matched' do
90
- subject.match?(/123/).should be_nil
91
- end
92
- it 'do not forward current position' do
93
- subject.match?(/\d{10}/)
94
- subject.pos.should == 0
95
- end
96
- end
97
- describe '#peek' do
98
- it 'returns MmapScanner' do
99
- subject.peek(10).should be_instance_of MmapScanner
100
- end
101
- it 'do not forward current position' do
102
- subject.peek(10)
103
- subject.pos.should == 0
104
- end
105
- end
106
- describe '#eos?' do
107
- it 'returns true if eos' do
108
- subject.pos = 10000
109
- subject.eos?.should == true
110
- end
111
- it 'returns false if not eos' do
112
- subject.pos = 9999
113
- subject.eos?.should == false
134
+
135
+ context 'with File' do
136
+ before do
137
+ tmpf = Tempfile.new 'mmapscanner'
138
+ tmpf.write '0123456789'*1000
139
+ @file = File.open(tmpf.path)
114
140
  end
115
- end
116
- describe '#rest' do
117
- it 'returns rest data as MmapScanner' do
118
- subject.pos = 9997
119
- ret = subject.rest
120
- ret.should be_instance_of MmapScanner
121
- ret.to_s.should == '789'
141
+ let(:src){@file}
142
+ subject{MmapScanner.new(src)}
143
+ it_should_behave_like 'MmapScanner'
144
+ describe '.new with position' do
145
+ it 'raise error when invalid position' do
146
+ expect{MmapScanner.new(@file, 4095)}.to raise_error(Errno::EINVAL)
147
+ end
122
148
  end
123
149
  end
124
- describe '.new with position' do
125
- it '#size is length of rest data' do
126
- MmapScanner.new(@file, 4096).size.should == 10000-4096
127
- end
128
- it 'raise error when invalid position' do
129
- expect{MmapScanner.new(@file, 4095)}.to raise_error(Errno::EINVAL)
130
- end
150
+
151
+ context 'with String' do
152
+ let(:src){'0123456789'*1020}
153
+ subject{MmapScanner.new(src, 100, 10000)}
154
+ it_should_behave_like 'MmapScanner'
131
155
  end
132
- describe '.new with length' do
133
- subject{MmapScanner.new(@file, nil, 10)}
134
- it '#size is specified size' do
135
- subject.size.should == 10
136
- end
137
- it 'raise error when negative' do
138
- expect{MmapScanner.new(@file, nil, -1)}.to raise_error(RangeError, 'length out of range: -1')
139
- end
156
+
157
+ context 'with MmapScanner' do
158
+ before do
159
+ tmpf = Tempfile.new 'mmapscanner'
160
+ tmpf.write '0123456789'*1020
161
+ @file = File.open(tmpf.path)
162
+ end
163
+ let(:src){MmapScanner.new(@file)}
164
+ subject{MmapScanner.new(src, 100, 10000)}
165
+ it_should_behave_like 'MmapScanner'
140
166
  end
141
167
  end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mmapscanner
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 3
5
- version: 0.1a
4
+ prerelease:
5
+ version: "0.2"
6
6
  platform: ruby
7
7
  authors:
8
8
  - TOMITA Masahiro
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-02-05 00:00:00 +09:00
13
+ date: 2011-03-02 00:00:00 +09:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -45,9 +45,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
45
45
  required_rubygems_version: !ruby/object:Gem::Requirement
46
46
  none: false
47
47
  requirements:
48
- - - ">"
48
+ - - ">="
49
49
  - !ruby/object:Gem::Version
50
- version: 1.3.1
50
+ version: "0"
51
51
  requirements: []
52
52
 
53
53
  rubyforge_project: