Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions spec/std/sprintf_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,18 @@ describe "::sprintf" do
assert_sprintf "%300.250d", 10.to_big_i ** 200, "#{" " * 50}#{"0" * 49}1#{"0" * 200}"
assert_sprintf "%- #300.250X", 16.to_big_i ** 200 - 1, " 0X#{"0" * 50}#{"F" * 200}#{" " * 47}"
end

it "works with BigFloat" do
assert_sprintf "%d", 123.to_big_f, "123"
assert_sprintf "%80.70d", 2.to_big_i ** 200, " 0000000001606938044258990275541962092341162602522202993782792835301376"
assert_sprintf "%- #70.60X", 2.to_big_f ** 200 - 2.to_big_f ** 120, " 0X0000000000FFFFFFFFFFFFFFFFFFFF000000000000000000000000000000 "
end

it "works with BigDecimal" do
assert_sprintf "%d", 123.to_big_d, "123"
assert_sprintf "%300.250d", 10.to_big_d ** 200, "#{" " * 50}#{"0" * 49}1#{"0" * 200}"
assert_sprintf "%- #300.250X", 16.to_big_d ** 200 - 1, " 0X#{"0" * 50}#{"F" * 200}#{" " * 47}"
end
end

it "doesn't stop at null character when doing '%'" do
Expand Down
7 changes: 7 additions & 0 deletions src/big/big_decimal.cr
Original file line number Diff line number Diff line change
Expand Up @@ -894,3 +894,10 @@ struct Crystal::Hasher
v &* value.sign
end
end

# :nodoc:
struct String::Formatter(A)
def int(flags, arg : BigDecimal) : Nil
int(flags, arg.to_big_i)
end
end
7 changes: 7 additions & 0 deletions src/big/big_float.cr
Original file line number Diff line number Diff line change
Expand Up @@ -671,3 +671,10 @@ module Math
BigFloat.new { |mpf| LibGMP.mpf_sqrt(mpf, value) }
end
end

# :nodoc:
struct String::Formatter(A)
def int(flags, arg : BigFloat) : Nil
int(flags, arg.to_big_i)
end
end
26 changes: 14 additions & 12 deletions src/string/formatter.cr
Original file line number Diff line number Diff line change
Expand Up @@ -269,33 +269,35 @@ struct String::Formatter(A)
pad arg.to_s.size, flags if flags.right_padding?
end

def int(flags, arg) : Nil
raise ArgumentError.new("Expected an integer, not #{arg.inspect}") unless arg.responds_to?(:to_i)
int = arg.is_a?(Int) ? arg : arg.to_i

precision = int_precision(int, flags)
base_str = int.to_s(flags.base, precision: precision, upcase: flags.uppercase?)
def int(flags, arg : Int) : Nil
precision = int_precision(arg, flags)
base_str = arg.to_s(flags.base, precision: precision, upcase: flags.uppercase?)
str_size = base_str.bytesize
str_size += 1 if int >= 0 && (flags.plus || flags.space)
str_size += 2 if flags.sharp && flags.base != 10 && int != 0
str_size += 1 if arg >= 0 && (flags.plus || flags.space)
str_size += 2 if flags.sharp && flags.base != 10 && arg != 0

# If `int` is zero-padded, we let the precision argument do the right-justification
# If `arg` is zero-padded, we let the precision argument do the right-justification
pad(str_size, flags) if flags.left_padding? && flags.padding_char != '0'

write_plus_or_space(int, flags)
write_plus_or_space(arg, flags)

if flags.sharp && int < 0
if flags.sharp && arg < 0
@io << '-'
write_base_prefix(flags)
@io.write_string base_str.unsafe_byte_slice(1)
else
write_base_prefix(flags) if flags.sharp && int != 0
write_base_prefix(flags) if flags.sharp && arg != 0
@io << base_str
end

pad(str_size, flags) if flags.right_padding?
end

def int(flags, arg) : Nil
raise ArgumentError.new("Expected an integer, not #{arg.inspect}") unless arg.responds_to?(:to_i)
int(flags, arg.to_i)
end

private def write_plus_or_space(arg, flags)
if arg >= 0
if flags.plus
Expand Down