ruby_sscanf 0.2.1 → 0.2.3
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 +4 -4
- data/README.md +5 -2
- data/lib/ruby_sscanf.rb +2 -124
- data/lib/ruby_sscanf/engine.rb +128 -0
- data/lib/ruby_sscanf/version.rb +1 -1
- data/ruby_sscanf.gemspec +2 -2
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3637116ff8d600da08dc6dbdda7176f920e2b7c
|
4
|
+
data.tar.gz: 2f1d07cacd079a28c3d57e572e6f5d8392d5664f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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
|
data/lib/ruby_sscanf/version.rb
CHANGED
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.
|
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.
|
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.
|
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-
|
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.
|
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.
|
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.
|
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.
|
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
|