mmapscanner 0.1a → 0.2

Sign up to get free protection for your applications and to get access to all the features.
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: