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,7 @@
1
+ describe "StringScanner#concat" do
2
+ it_behaves_like(:strscan_concat, :concat)
3
+ end
4
+
5
+ describe "StringScanner#concat when passed a Fixnum" do
6
+ it_behaves_like(:strscan_concat_fixnum, :concat)
7
+ end
@@ -0,0 +1,36 @@
1
+ describe "StringScanner#dup" do
2
+ before do
3
+ @string = "this is a test"
4
+ @orig_s = StringScanner.new(@string)
5
+ end
6
+
7
+ it "copies the passed StringScanner's content to self" do
8
+ s = @orig_s.dup
9
+ s.string.should == @string
10
+ end
11
+
12
+ it "copies the passed StringSCanner's position to self" do
13
+ @orig_s.pos = 5
14
+ s = @orig_s.dup
15
+ s.pos.should.equal(5)
16
+ end
17
+
18
+ it "copies previous match state" do
19
+ @orig_s.scan(/\w+/)
20
+ @orig_s.scan(/\s/)
21
+
22
+ @orig_s.pre_match.should == "this"
23
+
24
+ s = @orig_s.dup
25
+ s.pre_match.should == "this"
26
+
27
+ s.unscan
28
+ s.scan(/\s/).should == " "
29
+ end
30
+
31
+ it "copies the passed StringScanner scan pointer to self" do
32
+ @orig_s.terminate
33
+ s = @orig_s.dup
34
+ s.eos?.should.be_true
35
+ end
36
+ end
@@ -0,0 +1,46 @@
1
+ describe "StringScanner#[]" do
2
+ before do
3
+ @s = StringScanner.new("Fri Jun 13 2008 22:43")
4
+ end
5
+
6
+ it "returns nil if there is no current match" do
7
+ @s[0].should == nil
8
+ end
9
+
10
+ it "returns the n-th subgroup in the most recent match" do
11
+ @s.scan(/(\w+) (\w+) (\d+) /)
12
+ @s[0].should == "Fri Jun 13 "
13
+ @s[1].should == "Fri"
14
+ @s[2].should == "Jun"
15
+ @s[3].should == "13"
16
+ @s[-3].should == "Fri"
17
+ @s[-2].should == "Jun"
18
+ @s[-1].should == "13"
19
+ end
20
+
21
+ it "returns nil if index is outside of self" do
22
+ @s.scan(/(\w+) (\w+) (\d+) /)
23
+ @s[5].should == nil
24
+ @s[-5].should == nil
25
+ end
26
+
27
+ it "calls to_int on the given index" do
28
+ @s.scan(/(\w+) (\w+) (\d+) /)
29
+ @s[0.5].should == "Fri Jun 13 "
30
+ end
31
+
32
+ it "raises a TypeError if the given index is nil" do
33
+ @s.scan(/(\w+) (\w+) (\d+) /)
34
+ lambda { @s[nil]}.should.raise(TypeError)
35
+ end
36
+
37
+ it "raises a TypeError when a String is as argument" do
38
+ @s.scan(/(\w+) (\w+) (\d+) /)
39
+ lambda { @s["Fri"]}.should.raise(TypeError)
40
+ end
41
+
42
+ it "raises a TypeError when a Range is as argument" do
43
+ @s.scan(/(\w+) (\w+) (\d+) /)
44
+ lambda { @s[0..2]}.should.raise(TypeError)
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ describe "StringScanner#empty?" do
2
+ it_behaves_like(:strscan_eos, :empty?)
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.empty?
11
+ # }.should complain(/empty?.*obsolete.*eos?/)
12
+ #
13
+ # lambda {
14
+ # $VERBOSE = false
15
+ # s.empty?
16
+ # }.should_not complain
17
+ # ensure
18
+ # $VERBOSE = old
19
+ # end
20
+ # end
21
+ end
@@ -0,0 +1,3 @@
1
+ describe "StringScanner#eos?" do
2
+ it_behaves_like(:strscan_eos, :eos?)
3
+ end
@@ -0,0 +1,21 @@
1
+ describe "StringScanner#exist?" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the index of the first occurrence of the given pattern" do
7
+ @s.exist?(/s/).should == 4
8
+ @s.scan(/This is/)
9
+ @s.exist?(/s/).should == 6
10
+ end
11
+
12
+ it "returns 0 if the pattern is empty" do
13
+ @s.exist?(//).should == 0
14
+ end
15
+
16
+ it "returns nil if the pattern isn't found in the string" do
17
+ @s.exist?(/S/).should == nil
18
+ @s.scan(/This is/)
19
+ @s.exist?(/i/).should == nil
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ describe "StringScanner#get_byte" do
2
+ it_behaves_like :strscan_get_byte, :get_byte
3
+ end
@@ -0,0 +1,23 @@
1
+ describe "StringScanner#getbyte" do
2
+ it_behaves_like :strscan_get_byte, :getbyte
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.getbyte
11
+ # }.should complain(/getbyte.*obsolete.*get_byte/)
12
+ #
13
+ # lambda {
14
+ # $VERBOSE = false
15
+ # s.getbyte
16
+ # }.should_not complain
17
+ # ensure
18
+ # $VERBOSE = old
19
+ # end
20
+ # end
21
+
22
+ it_behaves_like :extract_range, :getbyte
23
+ end
@@ -0,0 +1,41 @@
1
+ describe "StringScanner#getch" do
2
+ before do
3
+ @kcode = $KCODE
4
+ end
5
+
6
+ after do
7
+ $KCODE = @kcode
8
+ end
9
+
10
+ it "scans one character and returns it" do
11
+ s = StringScanner.new('abc')
12
+ s.getch.should == "a"
13
+ s.getch.should == "b"
14
+ s.getch.should == "c"
15
+ end
16
+
17
+ # it "is multi-byte character sensitive" do
18
+ # $KCODE = 'EUC'
19
+ #
20
+ # # Japanese hiragana "A" in EUC-JP
21
+ # # src = "\244\242".encode("euc-jp")
22
+ # src = "\244\242".force_encoding("euc-jp")
23
+ #
24
+ # s = StringScanner.new(src)
25
+ # s.getch.should == src
26
+ # end
27
+
28
+ it "returns nil at the end of the string" do
29
+ # empty string case
30
+ s = StringScanner.new('')
31
+ s.getch.should == nil
32
+ s.getch.should == nil
33
+
34
+ # non-empty string case
35
+ s = StringScanner.new('a')
36
+ s.getch # skip one
37
+ s.getch.should == nil
38
+ end
39
+
40
+ it_behaves_like :extract_range, :getch
41
+ end
@@ -0,0 +1,25 @@
1
+ describe "StringScanner#initialize" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ # it "is a private method" do
7
+ # StringScanner.should.be.a.private_instance_method(:initialize)
8
+ # end
9
+
10
+ it "returns an instance of StringScanner" do
11
+ @s.should.be.kind_of(StringScanner)
12
+ @s.tainted?.should.be_false
13
+ @s.eos?.should.be_false
14
+ end
15
+
16
+ # it "converts the argument into a string using #to_str" do
17
+ # m = mock(:str)
18
+ #
19
+ # s = "test"
20
+ # m.should_receive(:to_str).and_return(s)
21
+ #
22
+ # scan = StringScanner.new(m)
23
+ # scan.string.should == s
24
+ # end
25
+ end
@@ -0,0 +1,17 @@
1
+ describe "StringScanner#inspect" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns a String object" do
7
+ @s.inspect.should.be.kind_of(String)
8
+ end
9
+
10
+ it "returns a string that represents the StringScanner object" do
11
+ @s.inspect.should == "#<StringScanner 0/14 @ \"This ...\">"
12
+ @s.scan_until /is/
13
+ @s.inspect.should == "#<StringScanner 4/14 \"This\" @ \" is a...\">"
14
+ @s.terminate
15
+ @s.inspect.should == "#<StringScanner fin>"
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ describe "StringScanner#match?" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the length of the match and the scan pointer is not advanced" do
7
+ @s.match?(/\w+/).should == 4
8
+ @s.match?(/\w+/).should == 4
9
+ @s.pos.should == 0
10
+ end
11
+
12
+ it "returns nil if there's no match" do
13
+ @s.match?(/\d+/).should == nil
14
+ @s.match?(/\s+/).should == nil
15
+ end
16
+
17
+ it "effects pre_match" do
18
+ @s.scan(/\w+/)
19
+ @s.scan(/\s/)
20
+
21
+ @s.pre_match.should == "This"
22
+ @s.match?(/\w+/)
23
+ @s.pre_match.should == "This "
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ describe "StringScanner#matched_size" do
2
+ it_behaves_like(:strscan_matched_size, :matched_size)
3
+ end
@@ -0,0 +1,37 @@
1
+ describe "StringScanner#matched" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the last matched string" do
7
+ @s.match?(/\w+/)
8
+ @s.matched.should == "This"
9
+ @s.getch
10
+ @s.matched.should == "T"
11
+ @s.get_byte
12
+ @s.matched.should == "h"
13
+ end
14
+
15
+ it "returns nil if there's no match" do
16
+ @s.match?(/\d+/)
17
+ @s.matched.should == nil
18
+ end
19
+
20
+ it_behaves_like :extract_range_matched, :matched
21
+ end
22
+
23
+ describe "StringScanner#matched?" do
24
+ before do
25
+ @s = StringScanner.new("This is a test")
26
+ end
27
+
28
+ it "returns true if the last match was successful" do
29
+ @s.match?(/\w+/)
30
+ @s.matched?.should.be_true
31
+ end
32
+
33
+ it "returns false if there's no match" do
34
+ @s.match?(/\d+/)
35
+ @s.matched?.should.be_false
36
+ end
37
+ end
@@ -0,0 +1,23 @@
1
+ # ruby_version_is "" ... "1.9" do
2
+ describe "StringScanner#matchedsize" do
3
+ it_behaves_like(:strscan_matched_size, :matchedsize)
4
+
5
+ # it "warns in verbose mode that the method is obsolete" do
6
+ # s = StringScanner.new("abc")
7
+ # begin
8
+ # old = $VERBOSE
9
+ # lambda {
10
+ # $VERBOSE = true
11
+ # s.matchedsize
12
+ # }.should complain(/matchedsize.*obsolete.*matched_size/)
13
+ #
14
+ # lambda {
15
+ # $VERBOSE = false
16
+ # s.matchedsize
17
+ # }.should_not complain
18
+ # ensure
19
+ # $VERBOSE = old
20
+ # end
21
+ # end
22
+ end
23
+ # end
@@ -0,0 +1,5 @@
1
+ describe "StringScanner.must_C_version" do
2
+ it "returns self" do
3
+ StringScanner.must_C_version.should == StringScanner
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ describe "StringScanner#peek" do
2
+ it_behaves_like(:strscan_peek, :peek)
3
+ end
4
+
@@ -0,0 +1,21 @@
1
+ describe "StringScanner#peep" do
2
+ it_behaves_like(:strscan_peek, :peep)
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.peep(1)
11
+ # }.should complain(/peep.*obsolete.*peek/)
12
+ #
13
+ # lambda {
14
+ # $VERBOSE = false
15
+ # s.peep(1)
16
+ # }.should_not complain
17
+ # ensure
18
+ # $VERBOSE = old
19
+ # end
20
+ # end
21
+ end
@@ -0,0 +1,7 @@
1
+ describe "StringScanner#pointer" do
2
+ it_behaves_like(:strscan_pos, :pointer)
3
+ end
4
+
5
+ describe "StringScanner#pointer=" do
6
+ it_behaves_like(:strscan_pos_set, :pointer=)
7
+ end
@@ -0,0 +1,7 @@
1
+ describe "StringScanner#pos" do
2
+ it_behaves_like(:strscan_pos, :pos)
3
+ end
4
+
5
+ describe "StringScanner#pos=" do
6
+ it_behaves_like(:strscan_pos_set, :pos=)
7
+ end
@@ -0,0 +1,24 @@
1
+ describe "StringScanner#post_match" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the post-match (in the regular expression sense) of the last scan" do
7
+ @s.post_match.should == nil
8
+ @s.scan(/\w+\s/)
9
+ @s.post_match.should == "is a test"
10
+ @s.getch
11
+ @s.post_match.should == "s a test"
12
+ @s.get_byte
13
+ @s.post_match.should == " a test"
14
+ @s.get_byte
15
+ @s.post_match.should == "a test"
16
+ end
17
+
18
+ it "returns nil if there's no match" do
19
+ @s.scan(/\s+/)
20
+ @s.post_match.should == nil
21
+ end
22
+
23
+ it_behaves_like :extract_range_matched, :post_match
24
+ end
@@ -0,0 +1,37 @@
1
+ describe "StringScanner#pre_match" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the pre-match (in the regular expression sense) of the last scan" do
7
+ @s.pre_match.should == nil
8
+ @s.scan(/\w+\s/)
9
+ @s.pre_match.should == ""
10
+ @s.getch
11
+ @s.pre_match.should == "This "
12
+ @s.get_byte
13
+ @s.pre_match.should == "This i"
14
+ @s.get_byte
15
+ @s.pre_match.should == "This is"
16
+ end
17
+
18
+ it "returns nil if there's no match" do
19
+ @s.scan(/\s+/)
20
+ @s.pre_match.should == nil
21
+ end
22
+
23
+ it "is more than just the data from the last match" do
24
+ @s.scan(/\w+/)
25
+ @s.scan_until(/a te/)
26
+ @s.pre_match.should == "This is "
27
+ end
28
+
29
+ it "is not changed when the scanner's position changes" do
30
+ @s.scan_until(/\s+/)
31
+ @s.pre_match.should == "This"
32
+ @s.pos -= 1
33
+ @s.pre_match.should == "This"
34
+ end
35
+
36
+ it_behaves_like :extract_range_matched, :pre_match
37
+ end
@@ -0,0 +1,12 @@
1
+ describe "StringScanner#reset" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "reset the scan pointer and clear matching data" do
7
+ @s.scan(/This/)
8
+ @s.reset
9
+ @s.pos.should == 0
10
+ @s.matched.should == nil
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ describe "StringScanner#rest_size" do
2
+ it_behaves_like(:strscan_rest_size, :rest_size)
3
+ end
@@ -0,0 +1,44 @@
1
+ describe "StringScanner#rest" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the rest of the string" do
7
+ @s.scan(/This\s+/)
8
+ @s.rest.should == "is a test"
9
+ end
10
+
11
+ it "returns self in the reset position" do
12
+ @s.reset
13
+ @s.rest.should == @s.string
14
+ end
15
+
16
+ it "returns an empty string in the terminate position" do
17
+ @s.terminate
18
+ @s.rest.should == ""
19
+ end
20
+
21
+ it_behaves_like :extract_range_matched, :rest
22
+
23
+ end
24
+
25
+ describe "StringScanner#rest?" do
26
+ before do
27
+ @s = StringScanner.new("This is a test")
28
+ end
29
+
30
+ it "returns true if there is more data in the string" do
31
+ @s.rest?.should.be_true
32
+ @s.scan(/This/)
33
+ @s.rest?.should.be_true
34
+ end
35
+
36
+ it "returns false if there is no more data in the string" do
37
+ @s.terminate
38
+ @s.rest?.should.be_false
39
+ end
40
+
41
+ it "is the opposite of eos?" do
42
+ @s.rest?.should.not == @s.eos?
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ describe "StringScanner#restsize" do
2
+ it_behaves_like(:strscan_rest_size, :restsize)
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.restsize
11
+ # }.should complain(/restsize.*obsolete.*rest_size/)
12
+ #
13
+ # lambda {
14
+ # $VERBOSE = false
15
+ # s.restsize
16
+ # }.should_not complain
17
+ # ensure
18
+ # $VERBOSE = old
19
+ # end
20
+ # end
21
+ end
@@ -0,0 +1,27 @@
1
+ describe "StringScanner#scan_full" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the number of bytes advanced" do
7
+ orig_pos = @s.pos
8
+ @s.scan_full(/This/, false, false).should == 4
9
+ @s.pos.should == orig_pos
10
+ end
11
+
12
+ it "returns the number of bytes advanced and advances the scan pointer if the second argument is true" do
13
+ @s.scan_full(/This/, true, false).should == 4
14
+ @s.pos.should == 4
15
+ end
16
+
17
+ it "returns the matched string if the third argument is true" do
18
+ orig_pos = @s.pos
19
+ @s.scan_full(/This/, false, true).should == "This"
20
+ @s.pos.should == orig_pos
21
+ end
22
+
23
+ it "returns the matched string if the third argument is true and advances the scan pointer if the second argument is true" do
24
+ @s.scan_full(/This/, true, true).should == "This"
25
+ @s.pos.should == 4
26
+ end
27
+ end
@@ -0,0 +1,50 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ describe "StringScanner#scan" do
4
+ before do
5
+ @s = StringScanner.new("This is a test")
6
+ end
7
+
8
+ it "returns the matched string" do
9
+ @s.scan(/\w+/).should == "This"
10
+ @s.scan(/.../).should == " is"
11
+ @s.scan(//).should == ""
12
+ @s.scan(/\s+/).should == " "
13
+ end
14
+
15
+ # ruby_version_is "1.9" do
16
+ it "returns the matched string for a multi byte string" do
17
+ m = StringScanner.new("Привет!")
18
+ m.scan(/[А-Яа-я]+/).should == "Привет"
19
+ m.rest.should == "!"
20
+ end
21
+ # end
22
+
23
+ it "treats ^ as matching from the beginning of the current position" do
24
+ @s.scan(/\w+/).should == "This"
25
+ @s.scan(/^\d/).should == nil
26
+ @s.scan(/^\s/).should == " "
27
+ end
28
+
29
+ it "returns nil if there's no match" do
30
+ @s.scan(/\d/).should == nil
31
+ end
32
+
33
+ it "returns nil when there is no more to scan" do
34
+ @s.scan(/[\w\s]+/).should == "This is a test"
35
+ @s.scan(/\w+/).should == nil
36
+ end
37
+
38
+ it "returns an empty string when the pattern matches empty" do
39
+ @s.scan(/.*/).should == "This is a test"
40
+ @s.scan(/.*/).should == ""
41
+ @s.scan(/./).should == nil
42
+ end
43
+
44
+ it "raises a TypeError if pattern isn't a Regexp" do
45
+ lambda { @s.scan("aoeu") }.should.raise(TypeError)
46
+ lambda { @s.scan(5) }.should.raise(TypeError)
47
+ lambda { @s.scan(:test) }.should.raise(TypeError)
48
+ # lambda { @s.scan(mock('x')) }.should.raise(TypeError)
49
+ end
50
+ end
@@ -0,0 +1,20 @@
1
+ describe "StringScanner#scan_until" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the substring up to and including the end of the match" do
7
+ @s.scan_until(/a/).should == "This is a"
8
+ @s.pre_match.should == "This is "
9
+ @s.post_match.should == " test"
10
+ end
11
+
12
+ it "returns nil if there's no match" do
13
+ @s.scan_until(/\d/).should == nil
14
+ end
15
+
16
+ it "can match anchors properly" do
17
+ @s.scan(/T/)
18
+ @s.scan_until(/^h/).should == "h"
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ describe "StringScanner#search_full" do
2
+ before do
3
+ @s = StringScanner.new("This is a test")
4
+ end
5
+
6
+ it "returns the number of bytes advanced" do
7
+ orig_pos = @s.pos
8
+ @s.search_full(/This/, false, false).should == 4
9
+ @s.pos.should == orig_pos
10
+ end
11
+
12
+ it "returns the number of bytes advanced and advances the scan pointer if the second argument is true" do
13
+ @s.search_full(/This/, true, false).should == 4
14
+ @s.pos.should == 4
15
+ end
16
+
17
+ it "returns the matched string if the third argument is true" do
18
+ orig_pos = @s.pos
19
+ @s.search_full(/This/, false, true).should == "This"
20
+ @s.pos.should == orig_pos
21
+ end
22
+
23
+ it "returns the matched string if the third argument is true and advances the scan pointer if the second argument is true" do
24
+ @s.search_full(/This/, true, true).should == "This"
25
+ @s.pos.should == 4
26
+ end
27
+ end