Skip to content

Commit bbbd66a

Browse files
committed
Shrink Crystal::System.print_error's body
1 parent 9b7fd8d commit bbbd66a

File tree

1 file changed

+29
-24
lines changed

1 file changed

+29
-24
lines changed

src/crystal/system/print_error.cr

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ module Crystal::System
6565
finish = ptr + format_len
6666
arg_index = 0
6767

68+
# The widest integer types supported by the format specifier are `%lld` and
69+
# `%llu`, which do not exceed 64 bits, so we only need 20 digits maximum
70+
# note that `chars` does not have to be null-terminated, since we are
71+
# only yielding a `Bytes`
72+
int_chars = uninitialized UInt8[20]
73+
6874
while ptr < finish
6975
next_percent = ptr
7076
while next_percent < finish && !(next_percent.value === '%')
@@ -94,20 +100,20 @@ module Crystal::System
94100
end
95101
when 'd'
96102
read_arg(Int::Primitive) do |arg|
97-
to_int_slice(arg, 10, true, width) { |bytes| yield bytes }
103+
yield to_int_slice(int_chars.to_slice, arg, 10, true, width)
98104
end
99105
when 'u'
100106
read_arg(Int::Primitive) do |arg|
101-
to_int_slice(arg, 10, false, width) { |bytes| yield bytes }
107+
yield to_int_slice(int_chars.to_slice, arg, 10, false, width)
102108
end
103109
when 'x'
104110
read_arg(Int::Primitive) do |arg|
105-
to_int_slice(arg, 16, false, width) { |bytes| yield bytes }
111+
yield to_int_slice(int_chars.to_slice, arg, 16, false, width)
106112
end
107113
when 'p'
108114
read_arg(Pointer(Void)) do |arg|
109115
yield "0x".to_slice
110-
to_int_slice(arg.address, 16, false, 2) { |bytes| yield bytes }
116+
yield to_int_slice(int_chars.to_slice, arg.address, 16, false, 2)
111117
end
112118
else
113119
yield Slice.new(next_percent, fmt_ptr + 1 - next_percent)
@@ -118,8 +124,8 @@ module Crystal::System
118124
end
119125

120126
private macro read_arg(type, &block)
121-
{{ block.args[0] }} = args[arg_index].as?({{ type }})
122-
if !{{ block.args[0] }}.nil?
127+
{{ block.args[0] }} = args[arg_index]
128+
if {{ block.args[0] }}.is_a?({{ type }})
123129
{{ block.body }}
124130
else
125131
yield "(???)".to_slice
@@ -140,28 +146,27 @@ module Crystal::System
140146
end
141147

142148
# simplified version of `Int#internal_to_s`
143-
protected def self.to_int_slice(num, base, signed, width, &)
149+
protected def self.to_int_slice(buf, num, base, signed, width)
144150
if num == 0
145-
yield "0".to_slice
146-
return
151+
"0".to_slice
152+
else
153+
# NOTE: do not factor out `num`! it is written this way to inhibit
154+
# unnecessary union dispatches
155+
case {signed, width}
156+
when {true, 2} then to_int_slice_impl(buf, LibC::LongLong.new!(num), base)
157+
when {true, 1} then to_int_slice_impl(buf, LibC::Long.new!(num), base)
158+
when {true, 0} then to_int_slice_impl(buf, LibC::Int.new!(num), base)
159+
when {false, 2} then to_int_slice_impl(buf, LibC::ULongLong.new!(num), base)
160+
when {false, 1} then to_int_slice_impl(buf, LibC::ULong.new!(num), base)
161+
else to_int_slice_impl(buf, LibC::UInt.new!(num), base)
162+
end
147163
end
164+
end
148165

149-
# Given sizeof(num) <= 64 bits, we need at most 20 bytes for `%d` or `%u`
150-
# note that `chars` does not have to be null-terminated, since we are
151-
# only yielding a `Bytes`
152-
chars = uninitialized UInt8[20]
153-
ptr_end = chars.to_unsafe + 20
166+
private def self.to_int_slice_impl(buf, num, base)
167+
ptr_end = buf.to_unsafe + buf.size
154168
ptr = ptr_end
155169

156-
num = case {signed, width}
157-
when {true, 2} then LibC::LongLong.new!(num)
158-
when {true, 1} then LibC::Long.new!(num)
159-
when {true, 0} then LibC::Int.new!(num)
160-
when {false, 2} then LibC::ULongLong.new!(num)
161-
when {false, 1} then LibC::ULong.new!(num)
162-
else LibC::UInt.new!(num)
163-
end
164-
165170
neg = num < 0
166171

167172
# do not assume Crystal constant initialization succeeds, hence not `DIGITS`
@@ -178,7 +183,7 @@ module Crystal::System
178183
ptr.value = '-'.ord.to_u8
179184
end
180185

181-
yield Slice.new(ptr, ptr_end - ptr)
186+
Slice.new(ptr, ptr_end - ptr)
182187
end
183188

184189
def self.print_exception(message, ex)

0 commit comments

Comments
 (0)