motion-strscan 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +63 -0
  3. data/lib/motion-strscan/string.rb +20 -0
  4. data/lib/motion-strscan/strscan.rb +676 -0
  5. data/lib/motion-strscan/version.rb +3 -0
  6. data/lib/motion-strscan.rb +8 -0
  7. data/spec/helpers/it_behaves_like.rb +27 -0
  8. data/spec/string_spec/_shared/slice.rb +244 -0
  9. data/spec/string_spec/byteslice_spec.rb +21 -0
  10. data/spec/strscan_spec/_shared/bol.rb +25 -0
  11. data/spec/strscan_spec/_shared/concat.rb +31 -0
  12. data/spec/strscan_spec/_shared/eos.rb +17 -0
  13. data/spec/strscan_spec/_shared/extract_range.rb +22 -0
  14. data/spec/strscan_spec/_shared/extract_range_matched.rb +22 -0
  15. data/spec/strscan_spec/_shared/get_byte.rb +28 -0
  16. data/spec/strscan_spec/_shared/matched_size.rb +21 -0
  17. data/spec/strscan_spec/_shared/peek.rb +44 -0
  18. data/spec/strscan_spec/_shared/pos.rb +83 -0
  19. data/spec/strscan_spec/_shared/rest_size.rb +18 -0
  20. data/spec/strscan_spec/_shared/terminate.rb +17 -0
  21. data/spec/strscan_spec/append_spec.rb +7 -0
  22. data/spec/strscan_spec/beginning_of_line_spec.rb +3 -0
  23. data/spec/strscan_spec/bol_spec.rb +3 -0
  24. data/spec/strscan_spec/check_spec.rb +13 -0
  25. data/spec/strscan_spec/check_until_spec.rb +14 -0
  26. data/spec/strscan_spec/clear_spec.rb +21 -0
  27. data/spec/strscan_spec/concat_spec.rb +7 -0
  28. data/spec/strscan_spec/dup_spec.rb +36 -0
  29. data/spec/strscan_spec/element_reference_spec.rb +46 -0
  30. data/spec/strscan_spec/empty_spec.rb +21 -0
  31. data/spec/strscan_spec/eos_spec.rb +3 -0
  32. data/spec/strscan_spec/exist_spec.rb +21 -0
  33. data/spec/strscan_spec/get_byte_spec.rb +3 -0
  34. data/spec/strscan_spec/getbyte_spec.rb +23 -0
  35. data/spec/strscan_spec/getch_spec.rb +41 -0
  36. data/spec/strscan_spec/initialize_spec.rb +25 -0
  37. data/spec/strscan_spec/inspect_spec.rb +17 -0
  38. data/spec/strscan_spec/match_spec.rb +25 -0
  39. data/spec/strscan_spec/matched_size_spec.rb +3 -0
  40. data/spec/strscan_spec/matched_spec.rb +37 -0
  41. data/spec/strscan_spec/matchedsize_spec.rb +23 -0
  42. data/spec/strscan_spec/must_C_version_spec.rb +5 -0
  43. data/spec/strscan_spec/peek_spec.rb +4 -0
  44. data/spec/strscan_spec/peep_spec.rb +21 -0
  45. data/spec/strscan_spec/pointer_spec.rb +7 -0
  46. data/spec/strscan_spec/pos_spec.rb +7 -0
  47. data/spec/strscan_spec/post_match_spec.rb +24 -0
  48. data/spec/strscan_spec/pre_match_spec.rb +37 -0
  49. data/spec/strscan_spec/reset_spec.rb +12 -0
  50. data/spec/strscan_spec/rest_size_spec.rb +3 -0
  51. data/spec/strscan_spec/rest_spec.rb +44 -0
  52. data/spec/strscan_spec/restsize_spec.rb +21 -0
  53. data/spec/strscan_spec/scan_full_spec.rb +27 -0
  54. data/spec/strscan_spec/scan_spec.rb +50 -0
  55. data/spec/strscan_spec/scan_until_spec.rb +20 -0
  56. data/spec/strscan_spec/search_full_spec.rb +27 -0
  57. data/spec/strscan_spec/skip_spec.rb +15 -0
  58. data/spec/strscan_spec/skip_until_spec.rb +15 -0
  59. data/spec/strscan_spec/string_spec.rb +37 -0
  60. data/spec/strscan_spec/terminate_spec.rb +3 -0
  61. data/spec/strscan_spec/unscan_spec.rb +26 -0
  62. metadata +172 -0
@@ -0,0 +1,244 @@
1
+ # encoding: utf-8
2
+
3
+ shared :string_slice do
4
+
5
+ it "returns the character code of the character at the given index" do
6
+ "hello".send(@method, 0).should == ?h
7
+ "hello".send(@method, -1).should == ?o
8
+ end
9
+
10
+ it "returns nil if index is outside of self" do
11
+ "hello".send(@method, 20).should == nil
12
+ "hello".send(@method, -20).should == nil
13
+
14
+ # TODO "".send(@method, 0).should == nil
15
+ "".send(@method, -1).should == nil
16
+ end
17
+
18
+ it "calls to_int on the given index" do
19
+ "hello".send(@method, 0.5).should == ?h
20
+
21
+ obj = 1.0
22
+ obj.respond_to?(:to_int).should == true
23
+ "hello".send(@method, obj).should == ?e
24
+ end
25
+
26
+ it "raises a TypeError if the given index is nil" do
27
+ lambda { "hello".send(@method, nil) }.should.raise(TypeError)
28
+ end
29
+
30
+ it "raises a TypeError if the given index can't be converted to an Integer" do
31
+ # lambda { "hello".send(@method, mock('x')) }.should.raise(TypeError)
32
+ lambda { "hello".send(@method, {})}.should.raise(TypeError)
33
+ lambda { "hello".send(@method, [])}.should.raise(TypeError)
34
+ end
35
+ end
36
+
37
+
38
+ shared :string_slice_index_length do
39
+ it "returns the substring starting at the given index with the given length" do
40
+ "hello there".send(@method, 0,0).should == ""
41
+ "hello there".send(@method, 0,1).should == "h"
42
+ "hello there".send(@method, 0,3).should == "hel"
43
+ "hello there".send(@method, 0,6).should == "hello "
44
+ "hello there".send(@method, 0,9).should == "hello the"
45
+ "hello there".send(@method, 0,12).should == "hello there"
46
+
47
+ "hello there".send(@method, 1,0).should == ""
48
+ "hello there".send(@method, 1,1).should == "e"
49
+ "hello there".send(@method, 1,3).should == "ell"
50
+ "hello there".send(@method, 1,6).should == "ello t"
51
+ "hello there".send(@method, 1,9).should == "ello ther"
52
+ "hello there".send(@method, 1,12).should == "ello there"
53
+
54
+ "hello there".send(@method, 3,0).should == ""
55
+ "hello there".send(@method, 3,1).should == "l"
56
+ "hello there".send(@method, 3,3).should == "lo "
57
+ "hello there".send(@method, 3,6).should == "lo the"
58
+ "hello there".send(@method, 3,9).should == "lo there"
59
+
60
+ "hello there".send(@method, 4,0).should == ""
61
+ "hello there".send(@method, 4,3).should == "o t"
62
+ "hello there".send(@method, 4,6).should == "o ther"
63
+ "hello there".send(@method, 4,9).should == "o there"
64
+
65
+ "foo".send(@method, 2,1).should == "o"
66
+ "foo".send(@method, 3,0).should == ""
67
+ "foo".send(@method, 3,1).should == ""
68
+
69
+ "".send(@method, 0,0).should == ""
70
+ "".send(@method, 0,1).should == ""
71
+
72
+ "x".send(@method, 0,0).should == ""
73
+ "x".send(@method, 0,1).should == "x"
74
+ "x".send(@method, 1,0).should == ""
75
+ "x".send(@method, 1,1).should == ""
76
+
77
+ "x".send(@method, -1,0).should == ""
78
+ "x".send(@method, -1,1).should == "x"
79
+
80
+ "hello there".send(@method, -3,2).should == "er"
81
+ end
82
+
83
+ it "always taints resulting strings when self is tainted" do
84
+ str = "hello world"
85
+ str.taint
86
+
87
+ str.send(@method, 0,0).tainted?.should == true
88
+ str.send(@method, 0,1).tainted?.should == true
89
+ str.send(@method, 2,1).tainted?.should == true
90
+ end
91
+
92
+ it "returns nil if the offset falls outside of self" do
93
+ "hello there".send(@method, 20,3).should == nil
94
+ "hello there".send(@method, -20,3).should == nil
95
+
96
+ "".send(@method, 1,0).should == nil
97
+ "".send(@method, 1,1).should == nil
98
+
99
+ "".send(@method, -1,0).should == nil
100
+ "".send(@method, -1,1).should == nil
101
+
102
+ "x".send(@method, 2,0).should == nil
103
+ "x".send(@method, 2,1).should == nil
104
+
105
+ "x".send(@method, -2,0).should == nil
106
+ "x".send(@method, -2,1).should == nil
107
+ end
108
+
109
+ it "returns nil if the length is negative" do
110
+ "hello there".send(@method, 4,-3).should == nil
111
+ "hello there".send(@method, -4,-3).should == nil
112
+ end
113
+
114
+ it "calls to_int on the given index and the given length" do
115
+ "hello".send(@method, 0.5, 1).should == "h"
116
+ "hello".send(@method, 0.5, 2.5).should == "he"
117
+ "hello".send(@method, 1, 2.5).should == "el"
118
+
119
+ # obj = mock('2')
120
+ # obj.should_receive(:to_int).exactly(4).times.and_return(2)
121
+
122
+ # "hello".send(@method, obj, 1).should == "l"
123
+ # "hello".send(@method, obj, obj).should == "ll"
124
+ # "hello".send(@method, 0, obj).should == "he"
125
+ end
126
+
127
+ it "raises a TypeError when idx or length can't be converted to an integer" do
128
+ lambda { "hello".send(@method, 'x', 0) }.should.raise(TypeError)
129
+ lambda { "hello".send(@method, 0, 'x') }.should.raise(TypeError)
130
+
131
+ # I'm deliberately including this here.
132
+ # It means that str.send(@method, other, idx) isn't supported.
133
+ lambda { "hello".send(@method, "", 0) }.should.raise(TypeError)
134
+ end
135
+
136
+ it "raises a TypeError when the given index or the given length is nil" do
137
+ lambda { "hello".send(@method, 1, nil) }.should.raise(TypeError)
138
+ lambda { "hello".send(@method, nil, 1) }.should.raise(TypeError)
139
+ lambda { "hello".send(@method, nil, nil) }.should.raise(TypeError)
140
+ end
141
+
142
+ # it "returns subclass instances" do
143
+ # s = StringSpecs::MyString.new("hello")
144
+ # s.send(@method, 0,0).should be_kind_of(StringSpecs::MyString)
145
+ # s.send(@method, 0,4).should be_kind_of(StringSpecs::MyString)
146
+ # s.send(@method, 1,4).should be_kind_of(StringSpecs::MyString)
147
+ # end
148
+ end
149
+
150
+ shared :string_slice_range do
151
+ it "returns the substring given by the offsets of the range" do
152
+ "hello there".send(@method, 1..1).should == "e"
153
+ "hello there".send(@method, 1..3).should == "ell"
154
+ "hello there".send(@method, 1...3).should == "el"
155
+ "hello there".send(@method, -4..-2).should == "her"
156
+ "hello there".send(@method, -4...-2).should == "he"
157
+ "hello there".send(@method, 5..-1).should == " there"
158
+ "hello there".send(@method, 5...-1).should == " ther"
159
+
160
+ "".send(@method, 0..0).should == ""
161
+
162
+ "x".send(@method, 0..0).should == "x"
163
+ "x".send(@method, 0..1).should == "x"
164
+ "x".send(@method, 0...1).should == "x"
165
+ "x".send(@method, 0..-1).should == "x"
166
+
167
+ "x".send(@method, 1..1).should == ""
168
+ "x".send(@method, 1..-1).should == ""
169
+ end
170
+
171
+ it "returns nil if the beginning of the range falls outside of self" do
172
+ "hello there".send(@method, 12..-1).should == nil
173
+ "hello there".send(@method, 20..25).should == nil
174
+ "hello there".send(@method, 20..1).should == nil
175
+ "hello there".send(@method, -20..1).should == nil
176
+ "hello there".send(@method, -20..-1).should == nil
177
+
178
+ "".send(@method, -1..-1).should == nil
179
+ "".send(@method, -1...-1).should == nil
180
+ "".send(@method, -1..0).should == nil
181
+ "".send(@method, -1...0).should == nil
182
+ end
183
+
184
+ it "returns an empty string if range.begin is inside self and > real end" do
185
+ "hello there".send(@method, 1...1).should == ""
186
+ "hello there".send(@method, 4..2).should == ""
187
+ "hello".send(@method, 4..-4).should == ""
188
+ "hello there".send(@method, -5..-6).should == ""
189
+ "hello there".send(@method, -2..-4).should == ""
190
+ "hello there".send(@method, -5..-6).should == ""
191
+ "hello there".send(@method, -5..2).should == ""
192
+
193
+ "".send(@method, 0...0).should == ""
194
+ "".send(@method, 0..-1).should == ""
195
+ "".send(@method, 0...-1).should == ""
196
+
197
+ "x".send(@method, 0...0).should == ""
198
+ "x".send(@method, 0...-1).should == ""
199
+ "x".send(@method, 1...1).should == ""
200
+ "x".send(@method, 1...-1).should == ""
201
+ end
202
+
203
+ it "always taints resulting strings when self is tainted" do
204
+ str = "hello world"
205
+ str.taint
206
+
207
+ str.send(@method, 0..0).tainted?.should == true
208
+ str.send(@method, 0...0).tainted?.should == true
209
+ str.send(@method, 0..1).tainted?.should == true
210
+ str.send(@method, 0...1).tainted?.should == true
211
+ str.send(@method, 2..3).tainted?.should == true
212
+ str.send(@method, 2..0).tainted?.should == true
213
+ end
214
+
215
+ # it "returns subclass instances" do
216
+ # s = StringSpecs::MyString.new("hello")
217
+ # s.send(@method, 0...0).should be_kind_of(StringSpecs::MyString)
218
+ # s.send(@method, 0..4).should be_kind_of(StringSpecs::MyString)
219
+ # s.send(@method, 1..4).should be_kind_of(StringSpecs::MyString)
220
+ # end
221
+ #
222
+ # it "calls to_int on range arguments" do
223
+ # from = mock('from')
224
+ # to = mock('to')
225
+ #
226
+ # # So we can construct a range out of them...
227
+ # from.should_receive(:<=>).twice.and_return(0)
228
+ #
229
+ # from.should_receive(:to_int).twice.and_return(1)
230
+ # to.should_receive(:to_int).twice.and_return(-2)
231
+ #
232
+ # "hello there".send(@method, from..to).should == "ello ther"
233
+ # "hello there".send(@method, from...to).should == "ello the"
234
+ # end
235
+ #
236
+ # it "works with Range subclasses" do
237
+ # a = "GOOD"
238
+ # range_incl = StringSpecs::MyRange.new(1, 2)
239
+ # range_excl = StringSpecs::MyRange.new(-3, -1, true)
240
+ #
241
+ # a.send(@method, range_incl).should == "OO"
242
+ # a.send(@method, range_excl).should == "OO"
243
+ # end
244
+ end
@@ -0,0 +1,21 @@
1
+ describe "String#byteslice" do
2
+ # it "needs to reviewed for spec completeness"
3
+
4
+ it_behaves_like :string_slice, :byteslice
5
+ end
6
+
7
+ describe "String#byteslice with index, length" do
8
+ it_behaves_like :string_slice_index_length, :byteslice
9
+ end
10
+
11
+ describe "String#byteslice with Range" do
12
+ it_behaves_like :string_slice_range, :byteslice
13
+ end
14
+
15
+ describe "String#byteslice on on non ASCII strings" do
16
+ it "returns byteslice of unicode strings" do
17
+ "\u3042".byteslice(1).should == "\x81".force_encoding("UTF-8")
18
+ "\u3042".byteslice(1, 2).should == "\x81\x82".force_encoding("UTF-8")
19
+ "\u3042".byteslice(1..2).should == "\x81\x82".force_encoding("UTF-8")
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ shared :strscan_bol do
2
+ it "returns true if the scan pointer is at the beginning of the line, false otherwise" do
3
+ s = StringScanner.new("This is a test")
4
+ s.send(@method).should.be_true
5
+ s.scan(/This/)
6
+ s.send(@method).should.be_false
7
+ s.terminate
8
+ s.send(@method).should.be_false
9
+
10
+ s = StringScanner.new("hello\nworld")
11
+ s.bol?.should.be_true
12
+ s.scan(/\w+/)
13
+ s.bol?.should.be_false
14
+ s.scan(/\n/)
15
+ s.bol?.should.be_true
16
+ s.unscan
17
+ s.bol?.should.be_false
18
+ end
19
+
20
+ it "returns true if the scan pointer is at the end of the line of an empty string." do
21
+ s = StringScanner.new('')
22
+ s.terminate
23
+ s.send(@method).should.be_true
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ shared :strscan_concat do
2
+ it "concatenates the given argument to self and returns self" do
3
+ s = StringScanner.new("hello ")
4
+ s.send(@method, 'world').should == s
5
+ s.string.should == "hello world"
6
+ s.eos?.should.be_false
7
+ end
8
+
9
+ it "raises a TypeError if the given argument can't be converted to a String" do
10
+ lambda { a = StringScanner.new('hello').send(@method, :world) }.should.raise(TypeError)
11
+ # lambda { a = StringScanner.new('hello').send(@method, mock('x')) }.should.raise(TypeError)
12
+ end
13
+ end
14
+
15
+ shared :strscan_concat_fixnum do
16
+ it "raises a TypeError" do
17
+ a = StringScanner.new("hello world")
18
+ lambda { a.send(@method, 333) }.should.raise(TypeError)
19
+ b = StringScanner.new("")
20
+ lambda { b.send(@method, (256 * 3 + 64)) }.should.raise(TypeError)
21
+ lambda { b.send(@method, -200) }.should.raise(TypeError)
22
+ end
23
+
24
+ # it "doesn't call to_int on the argument" do
25
+ # x = mock('x')
26
+ # x.respond_to?(:to_int).should == false
27
+ #
28
+ # lambda { "".send(@method, x) }.should.raise(TypeError)
29
+ # end
30
+ end
31
+
@@ -0,0 +1,17 @@
1
+ shared :strscan_eos do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "Returns true if the scan pointer is at the end of the string" do
7
+ @s.terminate
8
+ @s.send(@method).should.be_true
9
+
10
+ s = StringScanner.new('')
11
+ s.send(@method).should.be_true
12
+ end
13
+
14
+ it "Returns false if the scan pointer is not at the end of the string" do
15
+ @s.send(@method).should.be_false
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ shared :extract_range do
2
+ it "returns an instance of String when passed a String subclass" do
3
+ cls = Class.new(String)
4
+ sub = cls.new("abc")
5
+
6
+ s = StringScanner.new(sub)
7
+ ch = s.send(@method)
8
+ ch.should.not.be.kind_of(cls)
9
+ ch.should.be.an.instance_of(String)
10
+ end
11
+
12
+ it "taints the returned String if the input was tainted" do
13
+ str = 'abc'
14
+ str.taint
15
+
16
+ s = StringScanner.new(str)
17
+
18
+ s.send(@method).tainted?.should.be_true
19
+ s.send(@method).tainted?.should.be_true
20
+ s.send(@method).tainted?.should.be_true
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ shared :extract_range_matched do
2
+ it "returns an instance of String when passed a String subclass" do
3
+ cls = Class.new(String)
4
+ sub = cls.new("abc")
5
+
6
+ s = StringScanner.new(sub)
7
+ s.scan(/\w{1}/)
8
+
9
+ ch = s.send(@method)
10
+ ch.should.not.be.kind_of(cls)
11
+ ch.should.be.an.instance_of(String)
12
+ end
13
+
14
+ it "taints the returned String if the input was tainted" do
15
+ str = 'abc'
16
+ str.taint
17
+
18
+ s = StringScanner.new(str)
19
+ s.scan(/\w{1}/)
20
+ s.send(@method).tainted?.should.be_true
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ shared :strscan_get_byte do
2
+ it "scans one byte and returns it" do
3
+ s = StringScanner.new('abc5.')
4
+ s.send(@method).should == 'a'
5
+ s.send(@method).should == 'b'
6
+ s.send(@method).should == 'c'
7
+ s.send(@method).should == '5'
8
+ s.send(@method).should == '.'
9
+ end
10
+
11
+ it "is not multi-byte character sensitive" do
12
+ s = StringScanner.new("\244\242")
13
+ s.send(@method).should == "\244"
14
+ s.send(@method).should == "\242"
15
+ end
16
+
17
+ it "returns nil at the end of the string" do
18
+ # empty string case
19
+ s = StringScanner.new('')
20
+ s.send(@method).should == nil
21
+ s.send(@method).should == nil
22
+
23
+ # non-empty string case
24
+ s = StringScanner.new('a')
25
+ s.send(@method) # skip one
26
+ s.send(@method).should == nil
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ shared :strscan_matched_size do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the size of the most recent match" do
7
+ @s.check /This/
8
+ @s.send(@method).should == 4
9
+ @s.send(@method).should == 4
10
+ @s.scan //
11
+ @s.send(@method).should == 0
12
+ end
13
+
14
+ it "returns nil if there was no recent match" do
15
+ @s.send(@method).should == nil
16
+ @s.check /\d+/
17
+ @s.send(@method).should == nil
18
+ @s.terminate
19
+ @s.send(@method).should == nil
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ shared :strscan_peek do
2
+ before do
3
+ @s = StringScanner.new('This is a test')
4
+ end
5
+
6
+ it "returns at most the specified number of characters from the current position" do
7
+ @s.send(@method, 4).should == "This"
8
+ @s.pos.should == 0
9
+ @s.pos = 5
10
+ @s.send(@method, 2).should == "is"
11
+ @s.send(@method, 1000).should == "is a test"
12
+ end
13
+
14
+ it "returns an empty string when the passed argument is zero" do
15
+ @s.send(@method, 0).should == ""
16
+ end
17
+
18
+ it "raises a ArgumentError when the passed argument is negative" do
19
+ lambda { @s.send(@method, -2) }.should.raise(ArgumentError)
20
+ end
21
+
22
+ # it "raises a RangeError when the passed argument is a Bignum" do
23
+ # lambda { @s.send(@method, bignum_value) }.should.raise(RangeError)
24
+ # end
25
+
26
+ it "returns an instance of String when passed a String subclass" do
27
+ cls = Class.new(String)
28
+ sub = cls.new("abc")
29
+
30
+ s = StringScanner.new(sub)
31
+
32
+ ch = s.send(@method, 1)
33
+ ch.should.not.be.kind_of(cls)
34
+ ch.should.be.an.instance_of(String)
35
+ end
36
+
37
+ it "taints the returned String if the input was tainted" do
38
+ str = 'abc'
39
+ str.taint
40
+
41
+ s = StringScanner.new(str)
42
+ s.send(@method, 1).tainted?.should.be_true
43
+ end
44
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+
3
+ shared :strscan_pos do
4
+ before do
5
+ @s = StringScanner.new("This is a test")
6
+ @m = StringScanner.new("cölorfül")
7
+ end
8
+
9
+ it "returns the position of the scan pointer" do
10
+ @s.send(@method).should == 0
11
+ @s.scan_until /This is/
12
+ @s.send(@method).should == 7
13
+ @s.get_byte
14
+ @s.send(@method).should == 8
15
+ @s.terminate
16
+ @s.send(@method).should == 14
17
+ end
18
+
19
+ it "returns the position of the scan pointer for multibyte string" do
20
+ @m.send(@method).should == 0
21
+ @m.scan_until /cö/
22
+ @m.send(@method).should == 3
23
+ @m.get_byte
24
+ @m.send(@method).should == 4
25
+ @m.terminate
26
+ @m.send(@method).should == 10
27
+ end
28
+
29
+ it "returns 0 in the reset position" do
30
+ @s.reset
31
+ @s.send(@method).should == 0
32
+ end
33
+
34
+ it "returns the length of the string in the terminate position" do
35
+ @s.terminate
36
+ @s.send(@method).should == @s.string.length
37
+ end
38
+
39
+ it "returns the `bytesize` for multibyte string in the terminate position" do
40
+ @m.terminate
41
+ @m.send(@method).should == @m.string.bytesize
42
+ @m.send(@method).should >= @m.string.length
43
+ end
44
+ end
45
+
46
+ shared :strscan_pos_set do
47
+ before do
48
+ @s = StringScanner.new("This is a test")
49
+ @m = StringScanner.new("cölorfül")
50
+ end
51
+
52
+ it "modify the scan pointer" do
53
+ @s.send(@method, 5)
54
+ @s.rest.should == "is a test"
55
+ end
56
+
57
+ it "can poin position that greater than string length for multibyte string" do
58
+ @m.send(@method, 9)
59
+ @m.rest.should == "l"
60
+ end
61
+
62
+ it "positions from the end if the argument is negative" do
63
+ @s.send(@method, -2)
64
+ @s.rest.should == "st"
65
+ @s.pos.should == 12
66
+ end
67
+
68
+ it "positions from the end if the argument is negative for multibyte string" do
69
+ @m.send(@method, -3)
70
+ @m.rest.should == "ül"
71
+ @m.pos.should == 7
72
+ end
73
+
74
+ it "raises a RangeError if position too far backward" do
75
+ lambda {
76
+ @s.send(@method, -20)
77
+ }.should.raise(RangeError)
78
+ end
79
+
80
+ it "raises a RangeError when the passed argument is out of range" do
81
+ lambda { @s.send(@method, 20) }.should.raise(RangeError)
82
+ end
83
+ end
@@ -0,0 +1,18 @@
1
+ shared :strscan_rest_size do
2
+ before do
3
+ @s = StringScanner.new('This is a test')
4
+ end
5
+
6
+ it "Returns the length of the rest of the string" do
7
+ @s.send(@method).should == 14
8
+ @s.scan(/This/)
9
+ @s.send(@method).should == 10
10
+ @s.terminate
11
+ @s.send(@method).should == 0
12
+ end
13
+
14
+ it "is equivalent to rest.size" do
15
+ @s.scan(/This/)
16
+ @s.send(@method).should == @s.rest.size
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ shared :strscan_terminate do
4
+ it "set the scan pointer to the end of the string and clear matching data." do
5
+ s = StringScanner.new('This is a test')
6
+ s.send(@method)
7
+ s.bol?.should.be_false
8
+ s.eos?.should.be_true
9
+ end
10
+
11
+ it "set the scan pointer to the end of the string and clear matching data for multibyte string." do
12
+ s = StringScanner.new('cölorfül')
13
+ s.send(@method)
14
+ s.bol?.should.be_false
15
+ s.eos?.should.be_true
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ describe "StringScanner#<<" do
2
+ it_behaves_like :strscan_concat, :<<
3
+ end
4
+
5
+ describe "StringScanner#<< when passed a Fixnum" do
6
+ it_behaves_like :strscan_concat_fixnum, :<<
7
+ end
@@ -0,0 +1,3 @@
1
+ describe "StringScanner#beginning_of_line?" do
2
+ it_behaves_like(:strscan_bol, :beginning_of_line?)
3
+ end
@@ -0,0 +1,3 @@
1
+ describe "StringScanner#bol?" do
2
+ it_behaves_like(:strscan_bol, :bol?)
3
+ end
@@ -0,0 +1,13 @@
1
+ describe "StringScanner#check" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the value that scan would return, without advancing the scan pointer" do
7
+ @s.check(/This/).should == "This"
8
+ @s.matched.should == "This"
9
+ @s.pos.should == 0
10
+ @s.check(/is/).should == nil
11
+ @s.matched.should == nil
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ # require 'strscan'
2
+
3
+ describe "StringScanner#check_until" do
4
+ before do
5
+ @s = StringScanner.new("This is a test")
6
+ end
7
+
8
+ it "returns the same value of scan_until, but don't advances the scan pointer" do
9
+ @s.check_until(/a/).should == "This is a"
10
+ @s.pos.should == 0
11
+ @s.matched.should == "a"
12
+ @s.check_until(/test/).should == "This is a test"
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ describe "StringScanner#clear" do
2
+ it_behaves_like(:strscan_terminate, :clear)
3
+
4
+ # it "warns in verbose mode that the method is obsolete" do
5
+ # s = StringScanner.new("abc")
6
+ # begin
7
+ # old = $VERBOSE
8
+ # lambda {
9
+ # $VERBOSE = true
10
+ # s.clear
11
+ # }.should complain(/clear.*obsolete.*terminate/)
12
+ #
13
+ # lambda {
14
+ # $VERBOSE = false
15
+ # s.clear
16
+ # }.should_not complain
17
+ # ensure
18
+ # $VERBOSE = old
19
+ # end
20
+ # end
21
+ end