ruby_sscanf 0.2.1 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0bc62e85d57a5d9c3b5c8dcd4b5710be669d33e4
4
- data.tar.gz: e263651715d3557d7ff6933e933e406dc0deb8d2
3
+ metadata.gz: a3637116ff8d600da08dc6dbdda7176f920e2b7c
4
+ data.tar.gz: 2f1d07cacd079a28c3d57e572e6f5d8392d5664f
5
5
  SHA512:
6
- metadata.gz: 1695d80b48075693c685e2f8c0f2e31c54337cd11854ea73f97656b7f8ab9f875fff2a693ac3f113eb9e6854a5bc9c58531856c7f6c90a91542a33934b4dddba
7
- data.tar.gz: b98fecc6662d6d2a763e10616581bf9e8c0ccb83e4f20be90a580e0c638fdcc6cd5cc5a423552a278c4a3da755bab63f01fde3289ab2c41783a188b80b3df07b
6
+ metadata.gz: 8e761ffadd60be04a4bfd62c96476a3bd2c7d06cd0f94aadf30b76ade72205617b3efa340c4dac26615fc82f290c200b70d13b4bb2d60a0a96a293511e7bc39e
7
+ data.tar.gz: 9473f807205c1539e1960a9c8b6bbeeaa367ec816c2edf358fa0bd10e02174677520fecc7d26764c3444d33f8250c774fe92c6c901b3324c35ff84a1b8eda4c2
data/README.md CHANGED
@@ -46,8 +46,10 @@ cannot be matched to input data, processing stops at that point. Otherwise
46
46
  processing continues until all the format elements are done.
47
47
 
48
48
  Literal string components match themselves in the input string. If the literal
49
- has a trailing space, then this matches zero or more spaces.
50
- The special sequence '%%' matches one '%' in the input string.
49
+ has a trailing space, then this matches zero or more spaces. The backslash
50
+ character is used as a quoting character. Thus \\\\ is processed as a single \\.
51
+ The special sequence '%%' matches one '%' in the input string. This is
52
+ equivalent to the sequence \\%.
51
53
 
52
54
  The layouts of a format specifier are:
53
55
 
@@ -64,6 +66,7 @@ parsed. Note that a .precision field may be specified, but it is ignored.
64
66
  * The min_width is the minimum allowed run of characters in the set.
65
67
  * The max_width is the maximum allowed run of characters in the set.
66
68
  * The set field is a regular expression style [...] set.
69
+ * The regex field is a full blown regular expression followed by options.
67
70
 
68
71
  The supported format field values are:
69
72
  <br>
data/lib/ruby_sscanf.rb CHANGED
@@ -1,132 +1,10 @@
1
1
  require 'format_engine'
2
+ require_relative 'ruby_sscanf/engine'
2
3
  require_relative 'ruby_sscanf/version'
3
4
 
4
5
  #The String class is monkey patched to support sscanf.
5
6
  class String
6
7
 
7
- #A regular expression for decimal integers.
8
- RSF_DECIMAL = /[+-]?\d+/
9
-
10
- #A regular expression for unsigned decimal integers.
11
- RSF_UNSIGNED = /[+]?\d+/
12
-
13
- #A regular expression for hexadecimal integers.
14
- rsf_hex = /[+-]?(0[xX])?\h+/
15
- RSF_HEX_PARSE = lambda {parse(rsf_hex) ? dst << found.to_i(16) : :break}
16
- RSF_HEX_SKIP = lambda {parse(rsf_hex) || :break}
17
-
18
- #A regular expression for octal integers.
19
- RSF_OCTAL = /[+-]?(0[oO])?[0-7]+/
20
-
21
- #A regular expression for binary integers.
22
- RSF_BINARY = /[+-]?(0[bB])?[01]+/
23
-
24
- #A regular expression for flexible base integers.
25
- RSF_INTEGER = /[+-]?((0[xX]\h+)|(0[bB][01]+)|(0[oO]?[0-7]*)|([1-9]\d*))/
26
-
27
- #A regular expression for floating point and scientific notation numbers.
28
- rsf_float = /[+-]?\d+(\.\d+)?([eE][+-]?\d+)?/
29
- RSF_FLOAT_PARSE = lambda {parse(rsf_float) ? dst << found.to_f : :break}
30
- RSF_FLOAT_SKIP = lambda {parse(rsf_float) || :break}
31
-
32
- #A regular expression for rational numbers.
33
- RSF_RATIONAL = /[+-]?\d+\/\d+(r)?/
34
-
35
- #A regular expression for complex numbers.
36
- RSF_COMPLEX = %r{(?<num> \d+(\.\d+)?([eE][+-]?\d+)?){0}
37
- [+-]?\g<num>[+-]\g<num>[ij]
38
- }x
39
-
40
- #A regular expression for a string.
41
- RSF_STRING = /\S+/
42
-
43
- #A regular expression for quoted strings.
44
- RSF_QUOTED = /("([^\\"]|\\.)*")|('([^\\']|\\.)*')/
45
-
46
- #The standard handlers for formats with embedded regular expressions.
47
- RSF_RGX = lambda {parse(fmt.regex) ? dst << found : :break}
48
- RSF_RGX_SKIP = lambda {parse(fmt.regex) || :break}
49
-
50
-
51
- #Get the parsing engine. This is cached on a per-thread basis. That is to
52
- #say, each thread gets its own \FormatEngine::Engine instance.
53
- def self.get_parser_engine
54
-
55
- Thread.current[:ruby_sscanf_engine] ||= FormatEngine::Engine.new(
56
- "%a" => RSF_FLOAT_PARSE,
57
- "%*a" => RSF_FLOAT_SKIP,
58
-
59
- "%A" => RSF_FLOAT_PARSE,
60
- "%*A" => RSF_FLOAT_SKIP,
61
-
62
- "%b" => lambda {parse(RSF_BINARY) ? dst << found.to_i(2) : :break},
63
- "%*b" => lambda {parse(RSF_BINARY) || :break},
64
-
65
- "%c" => lambda {dst << grab},
66
- "%*c" => lambda {grab},
67
-
68
- "%d" => lambda {parse(RSF_DECIMAL) ? dst << found.to_i : :break},
69
- "%*d" => lambda {parse(RSF_DECIMAL) || :break},
70
-
71
- "%e" => RSF_FLOAT_PARSE,
72
- "%*e" => RSF_FLOAT_SKIP,
73
-
74
- "%E" => RSF_FLOAT_PARSE,
75
- "%*E" => RSF_FLOAT_SKIP,
76
-
77
- "%f" => RSF_FLOAT_PARSE,
78
- "%*f" => RSF_FLOAT_SKIP,
79
-
80
- "%F" => RSF_FLOAT_PARSE,
81
- "%*F" => RSF_FLOAT_SKIP,
82
-
83
- "%g" => RSF_FLOAT_PARSE,
84
- "%*g" => RSF_FLOAT_SKIP,
85
-
86
- "%G" => RSF_FLOAT_PARSE,
87
- "%*G" => RSF_FLOAT_SKIP,
88
-
89
- "%i" => lambda {parse(RSF_INTEGER) ? dst << found.to_i(0) : :break},
90
- "%*i" => lambda {parse(RSF_INTEGER) || :break},
91
-
92
- "%j" => lambda {parse(RSF_COMPLEX) ? dst << Complex(found) : :break},
93
- "%*j" => lambda {parse(RSF_COMPLEX) || :break},
94
-
95
- "%o" => lambda {parse(RSF_OCTAL) ? dst << found.to_i(8) : :break},
96
- "%*o" => lambda {parse(RSF_OCTAL) || :break},
97
-
98
- "%q" => lambda do
99
- if parse(RSF_QUOTED)
100
- dst << found[1..-2].gsub(/\\./) {|seq| seq[-1]}
101
- else
102
- :break
103
- end
104
- end,
105
-
106
- "%*q" => lambda {parse(RSF_QUOTED) || :break},
107
-
108
- "%r" => lambda {parse(RSF_RATIONAL) ? dst << found.to_r : :break},
109
- "%*r" => lambda {parse(RSF_RATIONAL) || :break},
110
-
111
- "%s" => lambda {parse(RSF_STRING) ? dst << found : :break},
112
- "%*s" => lambda {parse(RSF_STRING) || :break},
113
-
114
- "%u" => lambda {parse(RSF_UNSIGNED) ? dst << found.to_i : :break},
115
- "%*u" => lambda {parse(RSF_UNSIGNED) || :break},
116
-
117
- "%x" => RSF_HEX_PARSE,
118
- "%*x" => RSF_HEX_SKIP,
119
-
120
- "%X" => RSF_HEX_PARSE,
121
- "%*X" => RSF_HEX_SKIP,
122
-
123
- "%[" => RSF_RGX,
124
- "%*[" => RSF_RGX_SKIP,
125
-
126
- "%/" => RSF_RGX,
127
- "%*/" => RSF_RGX_SKIP)
128
- end
129
-
130
8
  #Scan the formatted input.
131
9
  def sscanf(format)
132
10
  String.get_parser_engine.do_parse(self, [], format)
@@ -134,7 +12,7 @@ class String
134
12
 
135
13
  #Get any unparsed text.
136
14
  def self.sscanf_unparsed
137
- String.get_parser_engine.unparsed
15
+ get_parser_engine.unparsed
138
16
  end
139
17
 
140
18
  end
@@ -0,0 +1,128 @@
1
+ #The String class is monkey patched to support sscanf.
2
+ class String
3
+
4
+ protected
5
+
6
+ #A regular expression for decimal integers.
7
+ RSF_DECIMAL = /[+-]?\d+/
8
+
9
+ #A regular expression for unsigned decimal integers.
10
+ RSF_UNSIGNED = /[+]?\d+/
11
+
12
+ #A regular expression for hexadecimal integers.
13
+ rsf_hex = /[+-]?(0[xX])?\h+/
14
+ RSF_HEX_PARSE = lambda {parse(rsf_hex) ? dst << found.to_i(16) : :break}
15
+ RSF_HEX_SKIP = lambda {parse(rsf_hex) || :break}
16
+
17
+ #A regular expression for octal integers.
18
+ RSF_OCTAL = /[+-]?(0[oO])?[0-7]+/
19
+
20
+ #A regular expression for binary integers.
21
+ RSF_BINARY = /[+-]?(0[bB])?[01]+/
22
+
23
+ #A regular expression for flexible base integers.
24
+ RSF_INTEGER = /[+-]?((0[xX]\h+)|(0[bB][01]+)|(0[oO]?[0-7]*)|([1-9]\d*))/
25
+
26
+ #A regular expression for floating point and scientific notation numbers.
27
+ rsf_float = /[+-]?\d+(\.\d+)?([eE][+-]?\d+)?/
28
+ RSF_FLOAT_PARSE = lambda {parse(rsf_float) ? dst << found.to_f : :break}
29
+ RSF_FLOAT_SKIP = lambda {parse(rsf_float) || :break}
30
+
31
+ #A regular expression for rational numbers.
32
+ RSF_RATIONAL = /[+-]?\d+\/\d+(r)?/
33
+
34
+ #A regular expression for complex numbers.
35
+ RSF_COMPLEX = %r{(?<num> \d+(\.\d+)?([eE][+-]?\d+)?){0}
36
+ [+-]?\g<num>[+-]\g<num>[ij]
37
+ }x
38
+
39
+ #A regular expression for a string.
40
+ RSF_STRING = /\S+/
41
+
42
+ #A regular expression for quoted strings.
43
+ RSF_QUOTED = /("([^\\"]|\\.)*")|('([^\\']|\\.)*')/
44
+
45
+ #The standard handlers for formats with embedded regular expressions.
46
+ RSF_RGX = lambda {parse(fmt.regex) ? dst << found : :break}
47
+ RSF_RGX_SKIP = lambda {parse(fmt.regex) || :break}
48
+
49
+
50
+ #Get the parsing engine. This is cached on a per-thread basis. That is to
51
+ #say, each thread gets its own \FormatEngine::Engine instance.
52
+ def self.get_parser_engine
53
+
54
+ Thread.current[:ruby_sscanf_engine] ||= FormatEngine::Engine.new(
55
+ "%a" => RSF_FLOAT_PARSE,
56
+ "%*a" => RSF_FLOAT_SKIP,
57
+
58
+ "%A" => RSF_FLOAT_PARSE,
59
+ "%*A" => RSF_FLOAT_SKIP,
60
+
61
+ "%b" => lambda {parse(RSF_BINARY) ? dst << found.to_i(2) : :break},
62
+ "%*b" => lambda {parse(RSF_BINARY) || :break},
63
+
64
+ "%c" => lambda {dst << grab},
65
+ "%*c" => lambda {grab},
66
+
67
+ "%d" => lambda {parse(RSF_DECIMAL) ? dst << found.to_i : :break},
68
+ "%*d" => lambda {parse(RSF_DECIMAL) || :break},
69
+
70
+ "%e" => RSF_FLOAT_PARSE,
71
+ "%*e" => RSF_FLOAT_SKIP,
72
+
73
+ "%E" => RSF_FLOAT_PARSE,
74
+ "%*E" => RSF_FLOAT_SKIP,
75
+
76
+ "%f" => RSF_FLOAT_PARSE,
77
+ "%*f" => RSF_FLOAT_SKIP,
78
+
79
+ "%F" => RSF_FLOAT_PARSE,
80
+ "%*F" => RSF_FLOAT_SKIP,
81
+
82
+ "%g" => RSF_FLOAT_PARSE,
83
+ "%*g" => RSF_FLOAT_SKIP,
84
+
85
+ "%G" => RSF_FLOAT_PARSE,
86
+ "%*G" => RSF_FLOAT_SKIP,
87
+
88
+ "%i" => lambda {parse(RSF_INTEGER) ? dst << found.to_i(0) : :break},
89
+ "%*i" => lambda {parse(RSF_INTEGER) || :break},
90
+
91
+ "%j" => lambda {parse(RSF_COMPLEX) ? dst << Complex(found) : :break},
92
+ "%*j" => lambda {parse(RSF_COMPLEX) || :break},
93
+
94
+ "%o" => lambda {parse(RSF_OCTAL) ? dst << found.to_i(8) : :break},
95
+ "%*o" => lambda {parse(RSF_OCTAL) || :break},
96
+
97
+ "%q" => lambda do
98
+ if parse(RSF_QUOTED)
99
+ dst << found[1..-2].gsub(/\\./) {|seq| seq[-1]}
100
+ else
101
+ :break
102
+ end
103
+ end,
104
+
105
+ "%*q" => lambda {parse(RSF_QUOTED) || :break},
106
+
107
+ "%r" => lambda {parse(RSF_RATIONAL) ? dst << found.to_r : :break},
108
+ "%*r" => lambda {parse(RSF_RATIONAL) || :break},
109
+
110
+ "%s" => lambda {parse(RSF_STRING) ? dst << found : :break},
111
+ "%*s" => lambda {parse(RSF_STRING) || :break},
112
+
113
+ "%u" => lambda {parse(RSF_UNSIGNED) ? dst << found.to_i : :break},
114
+ "%*u" => lambda {parse(RSF_UNSIGNED) || :break},
115
+
116
+ "%x" => RSF_HEX_PARSE,
117
+ "%*x" => RSF_HEX_SKIP,
118
+
119
+ "%X" => RSF_HEX_PARSE,
120
+ "%*X" => RSF_HEX_SKIP,
121
+
122
+ "%[" => RSF_RGX,
123
+ "%*[" => RSF_RGX_SKIP,
124
+
125
+ "%/" => RSF_RGX,
126
+ "%*/" => RSF_RGX_SKIP)
127
+ end
128
+ end
@@ -1,5 +1,5 @@
1
1
  #The ruby_sscanf doesn't really live here.
2
2
  module RubySscanf
3
3
  #The gem's version.
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.3"
5
5
  end
data/ruby_sscanf.gemspec CHANGED
@@ -22,12 +22,12 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.required_ruby_version = '>= 1.9.3'
24
24
 
25
- spec.add_runtime_dependency "format_engine", ">= 0.7.1"
25
+ spec.add_runtime_dependency "format_engine", ">= 0.7.2"
26
26
 
27
27
  spec.add_development_dependency "bundler", "~> 1.11"
28
28
  spec.add_development_dependency "rake", "~> 10.0"
29
29
  spec.add_development_dependency 'minitest', "~> 5.5.1"
30
- spec.add_development_dependency 'minitest_visible', ">= 0.1.0"
30
+ spec.add_development_dependency 'minitest_visible', ">= 0.1.1"
31
31
  spec.add_development_dependency 'rdoc', "~> 4.0.1"
32
32
 
33
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_sscanf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Camilleri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-23 00:00:00.000000000 Z
11
+ date: 2016-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: format_engine
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.7.1
19
+ version: 0.7.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.7.1
26
+ version: 0.7.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: 0.1.0
75
+ version: 0.1.1
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 0.1.0
82
+ version: 0.1.1
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rdoc
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,7 @@ files:
108
108
  - Rakefile
109
109
  - bench/bench.rb
110
110
  - lib/ruby_sscanf.rb
111
+ - lib/ruby_sscanf/engine.rb
111
112
  - lib/ruby_sscanf/version.rb
112
113
  - ruby_sscanf.gemspec
113
114
  - tests/scan_tests.rb