aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--lib/scanf.rb29
-rw-r--r--test/scanf/test_scanf.rb2
3 files changed, 28 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 02edf04e8e..bb3f451b12 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Thu Apr 1 13:20:50 2010 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/scanf.rb: support %a format. [ruby-dev:40650]
+
Thu Apr 1 12:04:10 2010 NAKAMURA Usaku <usa@ruby-lang.org>
* include/ruby/ruby.h (PRE_TIMET_PREFIX): define if configure doesn't
diff --git a/lib/scanf.rb b/lib/scanf.rb
index ffc0d90f49..dd6ba6c9d0 100644
--- a/lib/scanf.rb
+++ b/lib/scanf.rb
@@ -112,7 +112,7 @@ and <tt>tests/scanftests.rb</tt> for examples.)
[x,X]
Matches an optionally signed hexadecimal integer,
-[f,g,e,E]
+[a,e,f,g,A,E,F,G]
Matches an optionally signed floating-point number.
[s]
@@ -309,7 +309,22 @@ module Scanf
def skip; /^\s*%\*/.match(@spec_string); end
- def extract_float(s); s.to_f if s &&! skip; end
+ def extract_float(s)
+ return nil unless s &&! skip
+ if /\A(?<sign>[-+]?)0[xX](?<frac>\.\h+|\h+(?:\.\h*)?)[pP](?<exp>[-+]\d+)/ =~ s
+ f1, f2 = frac.split('.')
+ f = f1.hex
+ if f2
+ len = f2.length
+ if len > 0
+ f += f2.hex / (16.0 ** len)
+ end
+ end
+ (sign == ?- ? -1 : 1) * Math.ldexp(f, exp.to_i)
+ else
+ s.to_f
+ end
+ end
def extract_decimal(s); s.to_i if s &&! skip; end
def extract_hex(s); s.hex if s &&! skip; end
def extract_octal(s); s.oct if s &&! skip; end
@@ -409,12 +424,12 @@ module Scanf
[ "([-+][0-7]{1,#{$1.to_i-1}}|[0-7]{1,#{$1}})", :extract_octal ]
# %f
- when /%\*?[efgEFG]/
- [ '([-+]?(?:\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))', :extract_float ]
+ when /%\*?[aefgAEFG]/
+ [ '([-+]?(?:0[xX](?:\.\h+|\h+(?:\.\h*)?)[pP][-+]\d+|\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))', :extract_float ]
# %5f
- when /%\*?(\d+)[efgEFG]/
- [ '(?=[-+]?(?:\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))' +
+ when /%\*?(\d+)[aefgAEFG]/
+ [ '(?=[-+]?(?:0[xX](?:\.\h+|\h+(?:\.\h*)?)[pP][-+]\d+|\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))' +
"(\\S{1,#{$1}})", :extract_float ]
# %5s
@@ -491,7 +506,7 @@ module Scanf
attr_reader :string_left, :last_spec_tried,
:last_match_tried, :matched_count, :space
- SPECIFIERS = 'diuXxofFeEgGsc'
+ SPECIFIERS = 'diuXxofFeEgGscaA'
REGEX = /
# possible space, followed by...
(?:\s*
diff --git a/test/scanf/test_scanf.rb b/test/scanf/test_scanf.rb
index 2ec4e54d94..169ffe63a1 100644
--- a/test/scanf/test_scanf.rb
+++ b/test/scanf/test_scanf.rb
@@ -276,6 +276,8 @@ module ScanfTests
[ "%g", "+3.25", [3.25] ],
[ "%G", "+3.25e2", [325.0] ],
[ "%f", "3.z", [3.0] ],
+ [ "%a", "0X1P+10", [1024.0] ],
+ [ "%A", "0x1.deadbeefp+99", [1.1851510441583988e+30] ],
# Testing embedded matches including literal '[' behavior
[",%d,%f", ",10,1.1", [10,1.1] ],