motion-strscan 0.5.0

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 (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