mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
sprintf.c: rational 'f' format
* sprintf.c (rb_str_format): support rational 'f' format. [ruby-core:64382] [Bug #10136] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47214 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
22892ca6c2
commit
1d196e0d2b
4 changed files with 78 additions and 1 deletions
|
@ -1,3 +1,8 @@
|
|||
Mon Aug 18 17:06:27 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* sprintf.c (rb_str_format): support rational 'f' format.
|
||||
[ruby-core:64382] [Bug #10136]
|
||||
|
||||
Mon Aug 18 08:03:46 2014 SHIBATA Hiroshi <shibata.hiroshi@gmail.com>
|
||||
|
||||
* spec/default.mspec: use 2.2 definition.
|
||||
|
|
|
@ -771,7 +771,7 @@ ruby.$(OBJEXT): {$(VPATH)}ruby.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
|
|||
safe.$(OBJEXT): {$(VPATH)}safe.c $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}internal.h
|
||||
signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \
|
||||
$(VM_CORE_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}internal.h {$(VPATH)}ruby_atomic.h {$(VPATH)}eval_intern.h
|
||||
sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
|
||||
sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h {$(VPATH)}id.h \
|
||||
{$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h
|
||||
st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES)
|
||||
strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \
|
||||
|
|
67
sprintf.c
67
sprintf.c
|
@ -15,6 +15,7 @@
|
|||
#include "ruby/re.h"
|
||||
#include "ruby/encoding.h"
|
||||
#include "internal.h"
|
||||
#include "id.h"
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
@ -1022,12 +1023,78 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
|
|||
break;
|
||||
|
||||
case 'f':
|
||||
{
|
||||
VALUE val = GETARG(), num, den;
|
||||
int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
|
||||
long len;
|
||||
if (!RB_TYPE_P(val, T_RATIONAL)) {
|
||||
nextvalue = val;
|
||||
goto float_value;
|
||||
}
|
||||
if (!(flags&FPREC)) prec = default_float_precision;
|
||||
den = rb_rational_den(val);
|
||||
num = rb_rational_num(val);
|
||||
if (FIXNUM_P(num)) {
|
||||
if ((SIGNED_VALUE)num < 0) {
|
||||
long n = -FIX2LONG(num);
|
||||
num = LONG2FIX(n);
|
||||
sign = -1;
|
||||
}
|
||||
}
|
||||
else if (rb_num_negative_p(num)) {
|
||||
sign = -1;
|
||||
num = rb_funcallv(num, idUMinus, 0, 0);
|
||||
}
|
||||
if (den != INT2FIX(1) && prec > 1) {
|
||||
const ID idDiv = rb_intern("div");
|
||||
VALUE p10 = rb_int_positive_pow(10, prec);
|
||||
VALUE den_2 = rb_funcall(den, idDiv, 1, INT2FIX(2));
|
||||
num = rb_funcallv(num, '*', 1, &p10);
|
||||
num = rb_funcallv(num, '+', 1, &den_2);
|
||||
num = rb_funcallv(num, idDiv, 1, &den);
|
||||
}
|
||||
else if (prec >= 0) {
|
||||
zero = prec;
|
||||
}
|
||||
val = rb_obj_as_string(num);
|
||||
len = RSTRING_LEN(val) + zero;
|
||||
if (prec >= len) ++len; /* integer part 0 */
|
||||
if (sign || (flags&FSPACE)) ++len;
|
||||
if (prec > 0) ++len; /* period */
|
||||
CHECK(len > width ? len : width);
|
||||
if (width > len) {
|
||||
width -= (int)len;
|
||||
if (!(flags&FMINUS)) {
|
||||
FILL(' ', width);
|
||||
width = 0;
|
||||
}
|
||||
}
|
||||
if (sign || (flags&FSPACE)) buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
|
||||
len = RSTRING_LEN(val) + zero;
|
||||
t = RSTRING_PTR(val);
|
||||
if (len > prec)
|
||||
memcpy(&buf[blen], t, len - prec);
|
||||
else
|
||||
buf[blen++] = '0';
|
||||
blen += len - prec;
|
||||
if (prec > 0) buf[blen++] = '.';
|
||||
if (zero) FILL('0', zero);
|
||||
else if (prec > 0) {
|
||||
memcpy(&buf[blen], t + len - prec, prec);
|
||||
blen += prec;
|
||||
}
|
||||
if (width > 0) FILL(' ', width);
|
||||
RB_GC_GUARD(val);
|
||||
break;
|
||||
}
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'e':
|
||||
case 'E':
|
||||
/* TODO: rational support */
|
||||
case 'a':
|
||||
case 'A':
|
||||
float_value:
|
||||
{
|
||||
VALUE val = GETARG();
|
||||
double fval;
|
||||
|
|
|
@ -148,6 +148,11 @@ class TestSprintf < Test::Unit::TestCase
|
|||
assert_equal(" Inf", sprintf("% e", inf), '[ruby-dev:34002]')
|
||||
end
|
||||
|
||||
def test_rational
|
||||
assert_match(/\A0\.10+\z/, sprintf("%.60f", 0.1r))
|
||||
assert_match(/\A0\.3+\z/, sprintf("%.60f", 1/3r))
|
||||
end
|
||||
|
||||
def test_hash
|
||||
options = {:capture=>/\d+/}
|
||||
assert_equal("with options {:capture=>/\\d+/}", sprintf("with options %p" % options))
|
||||
|
|
Loading…
Add table
Reference in a new issue