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.
- checksums.yaml +7 -0
- data/README.md +63 -0
- data/lib/motion-strscan/string.rb +20 -0
- data/lib/motion-strscan/strscan.rb +676 -0
- data/lib/motion-strscan/version.rb +3 -0
- data/lib/motion-strscan.rb +8 -0
- data/spec/helpers/it_behaves_like.rb +27 -0
- data/spec/string_spec/_shared/slice.rb +244 -0
- data/spec/string_spec/byteslice_spec.rb +21 -0
- data/spec/strscan_spec/_shared/bol.rb +25 -0
- data/spec/strscan_spec/_shared/concat.rb +31 -0
- data/spec/strscan_spec/_shared/eos.rb +17 -0
- data/spec/strscan_spec/_shared/extract_range.rb +22 -0
- data/spec/strscan_spec/_shared/extract_range_matched.rb +22 -0
- data/spec/strscan_spec/_shared/get_byte.rb +28 -0
- data/spec/strscan_spec/_shared/matched_size.rb +21 -0
- data/spec/strscan_spec/_shared/peek.rb +44 -0
- data/spec/strscan_spec/_shared/pos.rb +83 -0
- data/spec/strscan_spec/_shared/rest_size.rb +18 -0
- data/spec/strscan_spec/_shared/terminate.rb +17 -0
- data/spec/strscan_spec/append_spec.rb +7 -0
- data/spec/strscan_spec/beginning_of_line_spec.rb +3 -0
- data/spec/strscan_spec/bol_spec.rb +3 -0
- data/spec/strscan_spec/check_spec.rb +13 -0
- data/spec/strscan_spec/check_until_spec.rb +14 -0
- data/spec/strscan_spec/clear_spec.rb +21 -0
- data/spec/strscan_spec/concat_spec.rb +7 -0
- data/spec/strscan_spec/dup_spec.rb +36 -0
- data/spec/strscan_spec/element_reference_spec.rb +46 -0
- data/spec/strscan_spec/empty_spec.rb +21 -0
- data/spec/strscan_spec/eos_spec.rb +3 -0
- data/spec/strscan_spec/exist_spec.rb +21 -0
- data/spec/strscan_spec/get_byte_spec.rb +3 -0
- data/spec/strscan_spec/getbyte_spec.rb +23 -0
- data/spec/strscan_spec/getch_spec.rb +41 -0
- data/spec/strscan_spec/initialize_spec.rb +25 -0
- data/spec/strscan_spec/inspect_spec.rb +17 -0
- data/spec/strscan_spec/match_spec.rb +25 -0
- data/spec/strscan_spec/matched_size_spec.rb +3 -0
- data/spec/strscan_spec/matched_spec.rb +37 -0
- data/spec/strscan_spec/matchedsize_spec.rb +23 -0
- data/spec/strscan_spec/must_C_version_spec.rb +5 -0
- data/spec/strscan_spec/peek_spec.rb +4 -0
- data/spec/strscan_spec/peep_spec.rb +21 -0
- data/spec/strscan_spec/pointer_spec.rb +7 -0
- data/spec/strscan_spec/pos_spec.rb +7 -0
- data/spec/strscan_spec/post_match_spec.rb +24 -0
- data/spec/strscan_spec/pre_match_spec.rb +37 -0
- data/spec/strscan_spec/reset_spec.rb +12 -0
- data/spec/strscan_spec/rest_size_spec.rb +3 -0
- data/spec/strscan_spec/rest_spec.rb +44 -0
- data/spec/strscan_spec/restsize_spec.rb +21 -0
- data/spec/strscan_spec/scan_full_spec.rb +27 -0
- data/spec/strscan_spec/scan_spec.rb +50 -0
- data/spec/strscan_spec/scan_until_spec.rb +20 -0
- data/spec/strscan_spec/search_full_spec.rb +27 -0
- data/spec/strscan_spec/skip_spec.rb +15 -0
- data/spec/strscan_spec/skip_until_spec.rb +15 -0
- data/spec/strscan_spec/string_spec.rb +37 -0
- data/spec/strscan_spec/terminate_spec.rb +3 -0
- data/spec/strscan_spec/unscan_spec.rb +26 -0
- 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,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
|