Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 878 lines (821 sloc) 26.291 kB
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1 /*
2 * MacRuby implementation of Ruby 1.9's sprintf.c.
3 *
4 * This file is covered by the Ruby license. See COPYING for more details.
5 *
9595725 update copyrights to 2011
Laurent Sansonetti authored
6 * Copyright (C) 2007-2011, Apple Inc. All rights reserved.
9c1d230 committing experimental branch content
Laurent Sansonetti authored
7 * Copyright (C) 1993-2007 Yukihiro Matsumoto
8 * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
9 * Copyright (C) 2000 Information-technology Promotion Agency, Japan
10 */
11
cb65416 the great schism, part I
Laurent Sansonetti authored
12 #include <stdarg.h>
13
d0898dd include/ruby/macruby.h -> macruby_internal.h
Laurent Sansonetti authored
14 #include "macruby_internal.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored
15 #include "ruby/encoding.h"
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
16 #include "encoding.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored
17
18 /*
19 * call-seq:
20 * format(format_string [, arguments...] ) => string
21 * sprintf(format_string [, arguments...] ) => string
22 *
23 * Returns the string resulting from applying <i>format_string</i> to
24 * any additional arguments. Within the format string, any characters
25 * other than format sequences are copied to the result.
26 *
27 * The syntax of a format sequence is follows.
28 *
29 * %[flags][width][.precision]type
30 *
31 * A format
32 * sequence consists of a percent sign, followed by optional flags,
33 * width, and precision indicators, then terminated with a field type
34 * character. The field type controls how the corresponding
35 * <code>sprintf</code> argument is to be interpreted, while the flags
36 * modify that interpretation.
37 *
38 * The field type characters are:
39 *
40 * Field | Integer Format
41 * ------+--------------------------------------------------------------
42 * b | Convert argument as a binary number.
43 * | Negative numbers will be displayed as a two's complement
44 * | prefixed with `..1'.
45 * B | Equivalent to `b', but uses an uppercase 0B for prefix
46 * | in the alternative format by #.
47 * d | Convert argument as a decimal number.
48 * i | Identical to `d'.
49 * o | Convert argument as an octal number.
50 * | Negative numbers will be displayed as a two's complement
51 * | prefixed with `..7'.
52 * u | Identical to `d'.
53 * x | Convert argument as a hexadecimal number.
54 * | Negative numbers will be displayed as a two's complement
55 * | prefixed with `..f' (representing an infinite string of
56 * | leading 'ff's).
57 * X | Equivalent to `x', but uses uppercase letters.
58 *
59 * Field | Float Format
60 * ------+--------------------------------------------------------------
61 * e | Convert floating point argument into exponential notation
62 * | with one digit before the decimal point as [-]d.dddddde[+-]dd.
63 * | The precision specifies the number of digits after the decimal
64 * | point (defaulting to six).
65 * E | Equivalent to `e', but uses an uppercase E to indicate
66 * | the exponent.
67 * f | Convert floating point argument as [-]ddd.dddddd,
68 * | where the precision specifies the number of digits after
69 * | the decimal point.
70 * g | Convert a floating point number using exponential form
71 * | if the exponent is less than -4 or greater than or
72 * | equal to the precision, or in dd.dddd form otherwise.
73 * | The precision specifies the number of significant digits.
74 * G | Equivalent to `g', but use an uppercase `E' in exponent form.
75 *
76 * Field | Other Format
77 * ------+--------------------------------------------------------------
78 * c | Argument is the numeric code for a single character or
79 * | a single character string itself.
80 * p | The valuing of argument.inspect.
81 * s | Argument is a string to be substituted. If the format
82 * | sequence contains a precision, at most that many characters
83 * | will be copied.
84 *
85 * The flags modifies the behavior of the formats.
86 * The flag characters are:
87 *
88 * Flag | Applies to | Meaning
89 * ---------+---------------+-----------------------------------------
90 * space | bBdiouxX | Leave a space at the start of
91 * | eEfgG | non-negative numbers.
92 * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
93 * | | a minus sign with absolute value for
94 * | | negative values.
95 * ---------+---------------+-----------------------------------------
96 * (digit)$ | all | Specifies the absolute argument number
97 * | | for this field. Absolute and relative
98 * | | argument numbers cannot be mixed in a
99 * | | sprintf string.
100 * ---------+---------------+-----------------------------------------
101 * # | bBoxX | Use an alternative format.
102 * | eEfgG | For the conversions `o', increase the precision
103 * | | until the first digit will be `0' if
104 * | | it is not formatted as complements.
105 * | | For the conversions `x', `X', `b' and `B'
106 * | | on non-zero, prefix the result with ``0x'',
107 * | | ``0X'', ``0b'' and ``0B'', respectively.
108 * | | For `e', `E', `f', `g', and 'G',
109 * | | force a decimal point to be added,
110 * | | even if no digits follow.
111 * | | For `g' and 'G', do not remove trailing zeros.
112 * ---------+---------------+-----------------------------------------
113 * + | bBdiouxX | Add a leading plus sign to non-negative
114 * | eEfgG | numbers.
115 * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
116 * | | a minus sign with absolute value for
117 * | | negative values.
118 * ---------+---------------+-----------------------------------------
119 * - | all | Left-justify the result of this conversion.
120 * ---------+---------------+-----------------------------------------
121 * 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
122 * | eEfgG | For `o', `x', `X', `b' and `B', radix-1
123 * | (numeric fmt) | is used for negative numbers formatted as
124 * | | complements.
125 * ---------+---------------+-----------------------------------------
126 * * | all | Use the next argument as the field width.
127 * | | If negative, left-justify the result. If the
128 * | | asterisk is followed by a number and a dollar
129 * | | sign, use the indicated argument as the width.
130 *
131 * Examples of flags:
132 *
133 * # `+' and space flag specifies the sign of non-negative numbers.
134 * sprintf("%d", 123) #=> "123"
135 * sprintf("%+d", 123) #=> "+123"
136 * sprintf("% d", 123) #=> " 123"
137 *
138 * # `#' flag for `o' increases number of digits to show `0'.
139 * # `+' and space flag changes format of negative numbers.
140 * sprintf("%o", 123) #=> "173"
141 * sprintf("%#o", 123) #=> "0173"
142 * sprintf("%+o", -123) #=> "-173"
143 * sprintf("%o", -123) #=> "..7605"
144 * sprintf("%#o", -123) #=> "..7605"
145 *
146 * # `#' flag for `x' add a prefix `0x' for non-zero numbers.
147 * # `+' and space flag disables complements for negative numbers.
148 * sprintf("%x", 123) #=> "7b"
149 * sprintf("%#x", 123) #=> "0x7b"
150 * sprintf("%+x", -123) #=> "-7b"
151 * sprintf("%x", -123) #=> "..f85"
152 * sprintf("%#x", -123) #=> "0x..f85"
153 * sprintf("%#x", 0) #=> "0"
154 *
155 * # `#' for `X' uses the prefix `0X'.
156 * sprintf("%X", 123) #=> "7B"
157 * sprintf("%#X", 123) #=> "0X7B"
158 *
159 * # `#' flag for `b' add a prefix `0b' for non-zero numbers.
160 * # `+' and space flag disables complements for negative numbers.
161 * sprintf("%b", 123) #=> "1111011"
162 * sprintf("%#b", 123) #=> "0b1111011"
163 * sprintf("%+b", -123) #=> "-1111011"
164 * sprintf("%b", -123) #=> "..10000101"
165 * sprintf("%#b", -123) #=> "0b..10000101"
166 * sprintf("%#b", 0) #=> "0"
167 *
168 * # `#' for `B' uses the prefix `0B'.
169 * sprintf("%B", 123) #=> "1111011"
170 * sprintf("%#B", 123) #=> "0B1111011"
171 *
172 * # `#' for `e' forces to show the decimal point.
173 * sprintf("%.0e", 1) #=> "1e+00"
174 * sprintf("%#.0e", 1) #=> "1.e+00"
175 *
176 * # `#' for `f' forces to show the decimal point.
177 * sprintf("%.0f", 1234) #=> "1234"
178 * sprintf("%#.0f", 1234) #=> "1234."
179 *
180 * # `#' for `g' forces to show the decimal point.
181 * # It also disables stripping lowest zeros.
182 * sprintf("%g", 123.4) #=> "123.4"
183 * sprintf("%#g", 123.4) #=> "123.400"
184 * sprintf("%g", 123456) #=> "123456"
185 * sprintf("%#g", 123456) #=> "123456."
186 *
187 * The field width is an optional integer, followed optionally by a
188 * period and a precision. The width specifies the minimum number of
189 * characters that will be written to the result for this field.
190 *
191 * Examples of width:
192 *
193 * # padding is done by spaces, width=20
194 * # 0 or radix-1. <------------------>
195 * sprintf("%20d", 123) #=> " 123"
196 * sprintf("%+20d", 123) #=> " +123"
197 * sprintf("%020d", 123) #=> "00000000000000000123"
198 * sprintf("%+020d", 123) #=> "+0000000000000000123"
199 * sprintf("% 020d", 123) #=> " 0000000000000000123"
200 * sprintf("%-20d", 123) #=> "123 "
201 * sprintf("%-+20d", 123) #=> "+123 "
202 * sprintf("%- 20d", 123) #=> " 123 "
203 * sprintf("%020x", -123) #=> "..ffffffffffffffff85"
204 *
205 * For
206 * numeric fields, the precision controls the number of decimal places
207 * displayed. For string fields, the precision determines the maximum
208 * number of characters to be copied from the string. (Thus, the format
209 * sequence <code>%10.10s</code> will always contribute exactly ten
210 * characters to the result.)
211 *
212 * Examples of precisions:
213 *
214 * # precision for `d', 'o', 'x' and 'b' is
215 * # minimum number of digits <------>
216 * sprintf("%20.8d", 123) #=> " 00000123"
217 * sprintf("%20.8o", 123) #=> " 00000173"
218 * sprintf("%20.8x", 123) #=> " 0000007b"
219 * sprintf("%20.8b", 123) #=> " 01111011"
220 * sprintf("%20.8d", -123) #=> " -00000123"
221 * sprintf("%20.8o", -123) #=> " ..777605"
222 * sprintf("%20.8x", -123) #=> " ..ffff85"
223 * sprintf("%20.8b", -11) #=> " ..110101"
224 *
225 * # "0x" and "0b" for `#x' and `#b' is not counted for
226 * # precision but "0" for `#o' is counted. <------>
227 * sprintf("%#20.8d", 123) #=> " 00000123"
228 * sprintf("%#20.8o", 123) #=> " 00000173"
229 * sprintf("%#20.8x", 123) #=> " 0x0000007b"
230 * sprintf("%#20.8b", 123) #=> " 0b01111011"
231 * sprintf("%#20.8d", -123) #=> " -00000123"
232 * sprintf("%#20.8o", -123) #=> " ..777605"
233 * sprintf("%#20.8x", -123) #=> " 0x..ffff85"
234 * sprintf("%#20.8b", -11) #=> " 0b..110101"
235 *
236 * # precision for `e' is number of
237 * # digits after the decimal point <------>
238 * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
239 *
240 * # precision for `f' is number of
241 * # digits after the decimal point <------>
242 * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
243 *
244 * # precision for `g' is number of
245 * # significant digits <------->
246 * sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
247 *
248 * # <------->
249 * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
250 *
251 * # precision for `s' is
252 * # maximum number of characters <------>
253 * sprintf("%20.8s", "string test") #=> " string t"
254 *
255 * Examples:
256 *
257 * sprintf("%d %04x", 123, 123) #=> "123 007b"
258 * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
259 * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
260 * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
261 * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
262 * sprintf("%u", -123) #=> "-123"
263 */
264
265 #define GETNTHARG(nth) \
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
266 ((nth >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : \
267 argv[nth])
9c1d230 committing experimental branch content
Laurent Sansonetti authored
268
269 VALUE
270 rb_f_sprintf_imp(VALUE recv, SEL sel, int argc, VALUE *argv)
271 {
272 return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
273 }
274
275 VALUE
276 rb_f_sprintf(int argc, const VALUE *argv)
277 {
278 return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
279 }
280
281 VALUE
282 rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
283 {
284 char buffer[512];
285 int n;
286 n = vsnprintf(buffer, sizeof buffer, fmt, ap);
287 return rb_enc_str_new(buffer, n, enc);
288 }
289
290 VALUE
291 rb_enc_sprintf(rb_encoding *enc, const char *format, ...)
292 {
293 va_list ap;
294 va_start(ap, format);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
295 VALUE result = rb_enc_vsprintf(enc, format, ap);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
296 va_end(ap);
297 return result;
298 }
299
300 VALUE
301 rb_vsprintf(const char *fmt, va_list ap)
302 {
303 return rb_enc_vsprintf(NULL, fmt, ap);
304 }
305
306 VALUE
307 rb_sprintf(const char *format, ...)
308 {
309 va_list ap;
310 va_start(ap, format);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
311 VALUE result = rb_vsprintf(format, ap);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
312 va_end(ap);
313 return result;
314 }
cb65416 the great schism, part I
Laurent Sansonetti authored
315
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
316 #define IS_NEG(num) RBIGNUM_NEGATIVE_P(num)
317 #define REL_REF 1
318 #define ABS_REF 2
319 #define NAMED_REF 3
320
321 #define REF_NAME(type) \
322 ((type) == REL_REF ? "relative" : (type) == ABS_REF ? "absolute" : "named")
323
324 #define SET_REF_TYPE(type) \
26e8df9 @Watson1978 sprintf() will be given the positional arguments and precision tokens…
Watson1978 authored
325 if (arg == 0 && ref_type != 0 && (type) != ref_type) { \
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
326 rb_raise(rb_eArgError, "can't mix %s references with %s references", \
327 REF_NAME(type), REF_NAME(ref_type)); \
328 } \
329 ref_type = (type);
330
331 #define GET_ARG() \
332 if (arg == 0) { \
333 SET_REF_TYPE(REL_REF); \
334 arg = GETNTHARG(j); \
335 j++; \
336 }
337
338 #define isprenum(ch) ((ch) == '-' || (ch) == ' ' || (ch) == '+')
339
cb65416 the great schism, part I
Laurent Sansonetti authored
340 static void
87717e7 some sprintf fixes
Laurent Sansonetti authored
341 pad_format_value(VALUE arg, long start, long width, VALUE pad)
cb65416 the great schism, part I
Laurent Sansonetti authored
342 {
87717e7 some sprintf fixes
Laurent Sansonetti authored
343 const long slen = rb_str_chars_len(arg);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
344 if (width <= slen) {
345 return;
346 }
347 if (start < 0) {
348 start += slen + 1;
349 }
350 width -= slen;
351 do {
87717e7 some sprintf fixes
Laurent Sansonetti authored
352 rb_str_update(arg, start, 0, pad);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
353 }
354 while (--width > 0);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
355 }
cb65416 the great schism, part I
Laurent Sansonetti authored
356
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
357 static long
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
358 cstr_update(UChar **str, long *str_len, long start, long num, VALUE replace)
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
359 {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
360 const long len = *str_len;
361 long replace_len = replace == 0 ? 0 : rb_str_chars_len(replace);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
362 if (start + num > len) {
363 num = len - start;
364 }
365 if (replace_len >= num) {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
366 *str_len = len + replace_len - num;
367 *str = (UChar *)xrealloc(*str,
368 sizeof(UChar) * (len + replace_len - num));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
369 }
370 if (replace_len != num) {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
371 bcopy(*str + start + num, *str + start + replace_len,
372 sizeof(UChar) * (len - start - num));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
373 }
374 if (replace_len > 0) {
d1673a2 introduce a better unichar API, which should be as fast as before the…
Laurent Sansonetti authored
375 RB_STR_GET_UCHARS(replace, replace_chars, replace_len2);
376 assert(replace_len2 == replace_len);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
377 bcopy(replace_chars, *str + start, sizeof(UChar) * replace_len);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
378 }
379 return replace_len - num;
380 }
381
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
382 static VALUE
87717e7 some sprintf fixes
Laurent Sansonetti authored
383 get_named_arg(UChar *format_str, long format_len, long *i, VALUE hash)
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
384 {
385 if (TYPE(hash) != T_HASH) {
386 rb_raise(rb_eArgError,
387 "hash required for named references");
388 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
389 UChar closing = format_str[(*i)++] + 2;
390 UChar *str_ptr = &format_str[*i];
18c6303 @Watson1978 fixed the bug of sprintf() within "%<named>" format
Watson1978 authored
391 long length = 0;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
392 while (*i < format_len && format_str[*i] != closing) {
393 (*i)++;
18c6303 @Watson1978 fixed the bug of sprintf() within "%<named>" format
Watson1978 authored
394 length++;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
395 }
396 if (*i == format_len) {
397 rb_raise(rb_eArgError,
398 "malformed name - unmatched parenthesis");
399 }
18c6303 @Watson1978 fixed the bug of sprintf() within "%<named>" format
Watson1978 authored
400 VALUE substr = rb_unicode_str_new(str_ptr, (size_t)length);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
401 hash = rb_hash_aref(hash, ID2SYM(rb_intern_str(substr)));
402 return hash;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
403 }
404
405 // XXX look for arguments that are altered but not duped
406 VALUE
407 rb_str_format(int argc, const VALUE *argv, VALUE fmt)
408 {
409 bool tainted = OBJ_TAINTED(fmt);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
410
411 long format_len = 0;
d1673a2 introduce a better unichar API, which should be as fast as before the…
Laurent Sansonetti authored
412 UChar *format_str = rb_str_xcopy_uchars(fmt, &format_len);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
413 if (format_len == 0) {
414 goto bail;
415 }
416
417 long num, pos;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
418 int j = 0;
419 int ref_type = 0;
87717e7 some sprintf fixes
Laurent Sansonetti authored
420 long format_str_capa = format_len;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
421
87717e7 some sprintf fixes
Laurent Sansonetti authored
422 for (long i = 0; i < format_len; i++) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
423 if (format_str[i] != '%') {
cb65416 the great schism, part I
Laurent Sansonetti authored
424 continue;
425 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
426 if (format_str[i + 1] == '%') {
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored
427 num = cstr_update(&format_str, &format_str_capa, i, 1, 0);
428 format_len += num;
cb65416 the great schism, part I
Laurent Sansonetti authored
429 continue;
430 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
431
432 bool sharp_flag = false;
433 bool space_flag = false;
434 bool plus_flag = false;
435 bool minus_flag = false;
436 bool zero_flag = false;
42f22c9 @Watson1978 sprintf() will throw an exception when was given width format twice.
Watson1978 authored
437 bool width_flag = false;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
438 bool precision_flag = false;
9031bde @Watson1978 sprintf() will throw an exception when was given named format twice.
Watson1978 authored
439 bool named_flag = false;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
440 bool complete = false;
441 VALUE arg = 0;
442 long width = 0;
443 long precision = 0;
444 int base = 0;
87717e7 some sprintf fixes
Laurent Sansonetti authored
445 VALUE negative_pad = 0;
446 VALUE sharp_pad = rb_str_new2("");
447 const long start = i;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
448
42f22c9 @Watson1978 sprintf() will throw an exception when was given width format twice.
Watson1978 authored
449 #define CHECK_FOR_WIDTH() \
450 if (width_flag) { \
451 rb_raise(rb_eArgError, "width given twice"); \
452 }
453
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
454 while (i++ < format_len) {
cb65416 the great schism, part I
Laurent Sansonetti authored
455 switch (format_str[i]) {
456 case '#':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
457 sharp_flag = true;
cb65416 the great schism, part I
Laurent Sansonetti authored
458 break;
459
460 case '*':
42f22c9 @Watson1978 sprintf() will throw an exception when was given width format twice.
Watson1978 authored
461 CHECK_FOR_WIDTH();
462 width_flag = true;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
463 if (format_str[++i] == '<' || format_str[i] == '{') {
464 SET_REF_TYPE(NAMED_REF);
465 width = NUM2LONG(rb_Integer(get_named_arg(format_str,
466 format_len, &i, GETNTHARG(0))));
467 }
468 else {
469 if (isprenum(format_str[i])) {
470 i--;
471 break;
472 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
473
474 num = rb_uchar_strtol(format_str, format_len, i, &pos);
475 if (pos == i--) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
476 SET_REF_TYPE(REL_REF);
477 width = NUM2LONG(rb_Integer(GETNTHARG(j)));
478 j++;
479 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
480 else if (format_str[pos] == '$') {
c9853df @Watson1978 String#% will throw an ArgumentError when was given "*0$" format.
Watson1978 authored
481 if (num == 0) {
482 rb_raise(rb_eArgError, "invalid absolute argument");
483 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
484 SET_REF_TYPE(ABS_REF);
485 width = NUM2LONG(rb_Integer(GETNTHARG(num - 1)));
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
486 i = pos;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
487 }
488 }
489 if (width < 0) {
490 minus_flag = true;
491 width = -width;
492 }
493 break;
494
495 case ' ':
496 if (!plus_flag) {
497 space_flag = true;
498 }
499 break;
500
501 case '+':
502 plus_flag = true;
503 space_flag = false;
504 break;
505
506 case '-':
507 zero_flag = false;
508 minus_flag = true;
509 break;
510
511 case '0':
512 if (!precision_flag && !minus_flag) {
513 zero_flag = true;
514 }
515 break;
516
517 case '1':
518 case '2':
519 case '3':
520 case '4':
521 case '5':
522 case '6':
523 case '7':
524 case '8':
525 case '9':
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
526 num = rb_uchar_strtol(format_str, format_len, i, &pos);
527 i = pos;
528 if (format_str[pos] == '$') {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
529 if (num == 0) {
530 rb_raise(rb_eArgError, "invalid absolute argument");
531 }
09f5ee7 @Watson1978 sprintf() will throw an exception when was given positional format tw…
Watson1978 authored
532 if (arg != 0) {
533 rb_raise(rb_eArgError, "value given twice");
534 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
535 SET_REF_TYPE(ABS_REF);
536 arg = GETNTHARG(num - 1);
537 }
538 else {
539 SET_REF_TYPE(REL_REF);
540 width = num;
541 i--;
42f22c9 @Watson1978 sprintf() will throw an exception when was given width format twice.
Watson1978 authored
542 CHECK_FOR_WIDTH();
543 width_flag = true;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
544 }
545 break;
546
547 case '.':
3314262 @Watson1978 sprintf() will throw an exception when was given precision format twice.
Watson1978 authored
548 if (precision_flag) {
549 rb_raise(rb_eArgError, "precision given twice");
550 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
551 precision_flag = true;
552 if (format_str[++i] == '*') {
553 if (format_str[++i] == '<' || format_str[i] == '{') {
554 SET_REF_TYPE(NAMED_REF);
555 precision = NUM2LONG(rb_Integer(get_named_arg(
556 format_str, format_len, &i, GETNTHARG(0))));
557 }
558 else {
559 if (isprenum(format_str[i])) {
560 i--;
561 break;
562 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
563
564 num = rb_uchar_strtol(format_str, format_len,
565 i, &pos);
225e90f @Watson1978 sprintf() will be given a format which is width's * and precision's *.
Watson1978 authored
566 if (format_str[pos] == '$') {
c9853df @Watson1978 String#% will throw an ArgumentError when was given "*0$" format.
Watson1978 authored
567 if (num == 0) {
568 rb_raise(rb_eArgError, "invalid absolute argument");
569 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
570 SET_REF_TYPE(ABS_REF);
571 precision = NUM2LONG(rb_Integer(GETNTHARG(
572 num - 1)));
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
573 i = pos;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
574 }
225e90f @Watson1978 sprintf() will be given a format which is width's * and precision's *.
Watson1978 authored
575 else {
576 SET_REF_TYPE(REL_REF);
577 precision = NUM2LONG(rb_Integer(GETNTHARG(j)));
578 j++;
579 i--;
580 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
581 }
582 }
583 else if (isdigit(format_str[i])) {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
584 precision = rb_uchar_strtol(format_str, format_len,
585 i, &pos);
586 i = pos - 1;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
587 }
588 else {
589 rb_raise(rb_eArgError, "invalid precision");
590 }
591
592 if (precision < 0) {
593 precision = 0;
594 }
595 break;
596
597 case '<':
598 case '{':
d8ba17f @Watson1978 fixed the bug of sprintf() within "%{named}" format.
Watson1978 authored
599 {
600 char term = (format_str[i] == '<') ? '>' : '}';
601
9031bde @Watson1978 sprintf() will throw an exception when was given named format twice.
Watson1978 authored
602 if (named_flag) {
603 rb_raise(rb_eArgError, "named given twice");
604 }
26e8df9 @Watson1978 sprintf() will be given the positional arguments and precision tokens…
Watson1978 authored
605 if (ref_type != 0) {
606 rb_raise(rb_eArgError, "named after numbered");
607 }
9031bde @Watson1978 sprintf() will throw an exception when was given named format twice.
Watson1978 authored
608 named_flag = true;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
609 SET_REF_TYPE(NAMED_REF);
610 arg = get_named_arg(format_str, format_len, &i,
611 GETNTHARG(0));
d8ba17f @Watson1978 fixed the bug of sprintf() within "%{named}" format.
Watson1978 authored
612 if (term == '}') {
613 if (TYPE(arg) != T_STRING) {
614 arg = rb_obj_as_string(arg);
615 }
616 goto format_s;
617 }
cb65416 the great schism, part I
Laurent Sansonetti authored
618 break;
d8ba17f @Watson1978 fixed the bug of sprintf() within "%{named}" format.
Watson1978 authored
619 }
cb65416 the great schism, part I
Laurent Sansonetti authored
620
621 case 'd':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
622 case 'D':
cb65416 the great schism, part I
Laurent Sansonetti authored
623 case 'i':
624 case 'u':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
625 case 'U':
626 base = 10;
627 complete = true;
eaf4b4a @Watson1978 Fixed the bug of sprintf. "#" flag should be ignored with "dDiuU" for…
Watson1978 authored
628 sharp_flag = false;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
629 break;
630
cb65416 the great schism, part I
Laurent Sansonetti authored
631 case 'x':
632 case 'X':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
633 base = 16;
87717e7 some sprintf fixes
Laurent Sansonetti authored
634 negative_pad = rb_str_new2("f");
635 sharp_pad = rb_str_new2("0x");
1017c7f @Watson1978 Fixed the bug of sprintf with format like a "%010.4f".
Watson1978 authored
636 if (precision_flag) {
637 zero_flag = false;
638 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
639 complete = true;
cb65416 the great schism, part I
Laurent Sansonetti authored
640 break;
641
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
642 case 'o':
643 case 'O':
644 base = 8;
87717e7 some sprintf fixes
Laurent Sansonetti authored
645 negative_pad = rb_str_new2("7");
646 sharp_pad = rb_str_new2("0");
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
647 complete = true;
cb65416 the great schism, part I
Laurent Sansonetti authored
648 break;
649
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
650 case 'B':
651 case 'b':
652 base = 2;
87717e7 some sprintf fixes
Laurent Sansonetti authored
653 negative_pad = rb_str_new2("1");
654 sharp_pad = rb_str_new2("0b");
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
655 complete = true;
cb65416 the great schism, part I
Laurent Sansonetti authored
656 break;
657
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
658 case 'c':
659 case 'C':
660 GET_ARG();
661 if (TYPE(arg) == T_STRING) {
abe5fa7 @Watson1978 sprintf("%c") will throw an exception when does not pass one character.
Watson1978 authored
662 if(RSTRING_LEN(arg) != 1) {
663 rb_raise(rb_eArgError, "%%c requires a character");
664 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
665 }
666 else {
110e345 fixed some bugs in Numeric#chr
Laurent Sansonetti authored
667 long num = NUM2LONG(arg);
668 if (num < 0 || i > 0xff) {
669 rb_raise(rb_eRangeError, "%ld out of char range",
670 num);
671 }
672 char c = (char)num;
673 arg = rb_str_new(&c, 1);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
674 }
675 complete = true;
676 break;
677
678 case 'f':
cb65416 the great schism, part I
Laurent Sansonetti authored
679 case 'F':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
680 case 'e':
cb65416 the great schism, part I
Laurent Sansonetti authored
681 case 'E':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
682 case 'g':
cb65416 the great schism, part I
Laurent Sansonetti authored
683 case 'G':
684 case 'a':
685 case 'A':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
686 {
687 // here we construct a new format str and then use
688 // c's sprintf. why? because floats are retarded
689 GET_ARG();
690 double value = RFLOAT_VALUE(rb_Float(arg));
691 complete = true;
692
693 if (isnan(value) || isinf(value)) {
694 arg = rb_str_new2((char *)(isnan(value) ? "NaN" :
695 value < 0 ? "-Inf" : "Inf"));
696 if (isnan(value) || value > 0) {
697 if (plus_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored
698 rb_str_update(arg, 0, 0, rb_str_new2("+"));
cb65416 the great schism, part I
Laurent Sansonetti authored
699 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
700 else if (space_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored
701 rb_str_update(arg, 0, 0, rb_str_new2(" "));
cb65416 the great schism, part I
Laurent Sansonetti authored
702 }
703 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
704 break;
705 }
706
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
707 arg = rb_unicode_str_new(&format_str[i], 1);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
708 if (precision_flag) {
709 rb_str_update(arg, 0, 0, rb_big2str(LONG2NUM(precision),
710 10));
87717e7 some sprintf fixes
Laurent Sansonetti authored
711 rb_str_update(arg, 0, 0, rb_str_new2("."));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
712 }
713 rb_str_update(arg, 0, 0, rb_big2str(LONG2NUM(width), 10));
714 if (minus_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored
715 rb_str_update(arg, 0, 0, rb_str_new2("-"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
716 }
717 else if (zero_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored
718 rb_str_update(arg, 0, 0, rb_str_new2("0"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
719 }
720 if (plus_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored
721 rb_str_update(arg, 0, 0, rb_str_new2("+"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
722 }
723 else if (space_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored
724 rb_str_update(arg, 0, 0, rb_str_new2(" "));
cb65416 the great schism, part I
Laurent Sansonetti authored
725 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
726 if (sharp_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored
727 rb_str_update(arg, 0, 0, rb_str_new2("#"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
728 }
87717e7 some sprintf fixes
Laurent Sansonetti authored
729 rb_str_update(arg, 0, 0, rb_str_new2("%"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
730
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
731 char *ptr;
732 asprintf(&ptr, RSTRING_PTR(arg), value);
733 arg = rb_str_new2(ptr);
734 free(ptr);
cb65416 the great schism, part I
Laurent Sansonetti authored
735 break;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
736 }
cb65416 the great schism, part I
Laurent Sansonetti authored
737
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
738 case 's':
739 case 'S':
cb65416 the great schism, part I
Laurent Sansonetti authored
740 case 'p':
741 case '@':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
742 GET_ARG();
87717e7 some sprintf fixes
Laurent Sansonetti authored
743 arg = (tolower(format_str[i]) != 's'
744 ? rb_inspect(arg) : TYPE(arg) == T_STRING
745 ? rb_str_new3(arg) : rb_obj_as_string(arg));
d8ba17f @Watson1978 fixed the bug of sprintf() within "%{named}" format.
Watson1978 authored
746 format_s:
87717e7 some sprintf fixes
Laurent Sansonetti authored
747 if (precision_flag && precision < rb_str_chars_len(arg)) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
748 CFStringPad((CFMutableStringRef)arg, NULL, precision,
749 0);
cb65416 the great schism, part I
Laurent Sansonetti authored
750 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
751 complete = true;
cb65416 the great schism, part I
Laurent Sansonetti authored
752 break;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
753
b62b438 @Watson1978 modified the style of r4928.
Watson1978 authored
754 case '\n':
755 case '\0':
756 if (format_str[i - 1] == '%') {
421ab55 @Watson1978 sprintf() will not throw exception when passed the format of single %…
Watson1978 authored
757 if (format_str[i] == '\n') {
758 arg = rb_str_new("%\n", 2);
759 }
760 else {
b62b438 @Watson1978 modified the style of r4928.
Watson1978 authored
761 if (format_len > i) {
762 arg = rb_str_new("%\0", 2);
763 }
764 else {
765 arg = rb_str_new("%", 1);
766 }
421ab55 @Watson1978 sprintf() will not throw exception when passed the format of single %…
Watson1978 authored
767 }
768 complete = true;
b62b438 @Watson1978 modified the style of r4928.
Watson1978 authored
769 break;
421ab55 @Watson1978 sprintf() will not throw exception when passed the format of single %…
Watson1978 authored
770 }
b62b438 @Watson1978 modified the style of r4928.
Watson1978 authored
771 rb_raise(rb_eArgError, "malformed format string - %%%c",
772 format_str[i]);
773 break;
774
775 default:
776 rb_raise(rb_eArgError, "malformed format string - %%%c",
777 format_str[i]);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
778 }
779 if (!complete) {
780 continue;
cb65416 the great schism, part I
Laurent Sansonetti authored
781 }
782
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
783 GET_ARG();
cb65416 the great schism, part I
Laurent Sansonetti authored
784
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
785 if (base != 0) {
786 bool sign_pad = false;
787 unsigned long num_index = 0;
3e1645b @Watson1978 Fixed the bug of sprintf with format "%# x".
Watson1978 authored
788 unsigned long sharp_beg = 0;
87717e7 some sprintf fixes
Laurent Sansonetti authored
789 VALUE zero_pad = rb_str_new2("0");
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
790
791 VALUE num = rb_Integer(arg);
792 if (TYPE(num) == T_FIXNUM) {
793 num = rb_int2big(FIX2LONG(num));
cb65416 the great schism, part I
Laurent Sansonetti authored
794 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
795 if (plus_flag || space_flag) {
796 sign_pad = 1;
797 }
798 if (IS_NEG(num)) {
799 num_index = 1;
3e1645b @Watson1978 Fixed the bug of sprintf with format "%# x".
Watson1978 authored
800 sharp_beg = 1;
87717e7 some sprintf fixes
Laurent Sansonetti authored
801 if (!sign_pad && negative_pad != 0) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
802 zero_pad = negative_pad;
803 num = rb_big_clone(num);
804 rb_big_2comp(num);
805 }
cb65416 the great schism, part I
Laurent Sansonetti authored
806 }
807
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
808 arg = rb_big2str(num, base);
87717e7 some sprintf fixes
Laurent Sansonetti authored
809 if (!sign_pad && IS_NEG(num) && negative_pad != 0) {
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored
810 UChar neg = rb_str_get_uchar(negative_pad, 0);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
811 if (base == 8) {
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored
812 UChar c = rb_str_get_uchar(arg, 1);
813 const long len = rb_str_chars_len(arg) - 1;
814 c |= ((~0 << 3) >> ((3 * len)
815 % (sizeof(BDIGIT) * 8))) & ~(~0 << 3);
816 rb_str_update(arg, 1, 1, rb_unicode_str_new(&c, 1));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
817 }
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored
818 for (int i = 1, count = rb_str_chars_len(arg); i < count;
819 i++) {
820 if (rb_str_get_uchar(arg, i) != neg) {
821 break;
822 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
823 num_index++;
824 }
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored
825 rb_str_update(arg, 0, num_index, negative_pad);
826 rb_str_update(arg, 0, 0, rb_str_new2(".."));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
827 num_index = 2;
3e1645b @Watson1978 Fixed the bug of sprintf with format "%# x".
Watson1978 authored
828 sharp_beg = 0;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
829 }
830 if (precision_flag) {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
831 pad_format_value(arg, num_index,
832 precision + (IS_NEG(num)
87717e7 some sprintf fixes
Laurent Sansonetti authored
833 && (sign_pad || negative_pad == 0) ? 1 : 0),
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
834 zero_pad);
835 }
e9d7b0c sprintf can now be free of C++ evil
Laurent Sansonetti authored
836 if (sharp_flag && rb_cmpint(num, Qfalse, Qfalse) != 0) {
3e1645b @Watson1978 Fixed the bug of sprintf with format "%# x".
Watson1978 authored
837 rb_str_update(arg, sharp_beg, 0, (VALUE)sharp_pad);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
838 num_index += 2;
839 }
840 if (sign_pad && RBIGNUM_POSITIVE_P(num)) {
841 rb_str_update(arg, 0, 0, (VALUE)(plus_flag ?
87717e7 some sprintf fixes
Laurent Sansonetti authored
842 rb_str_new2("+") : rb_str_new2(" ")));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
843 num_index++;
844 }
845 if (zero_flag) {
846 pad_format_value(arg, num_index, width, zero_pad);
847 }
848 if (ISUPPER(format_str[i])) {
849 CFStringUppercase((CFMutableStringRef)arg, NULL);
850 }
851 }
852
853 if (OBJ_TAINTED(arg)) {
854 tainted = true;
855 }
cb65416 the great schism, part I
Laurent Sansonetti authored
856
d6e38f5 #sprintf: don't try to mutate symbols
Laurent Sansonetti authored
857 if (TYPE(arg) == T_SYMBOL) {
858 // Because symbols are not mutable and pad_format_value()
859 // mutates its first argument.
860 arg = rb_sym_to_s(arg);
861 }
87717e7 some sprintf fixes
Laurent Sansonetti authored
862 pad_format_value(arg, minus_flag ? -1 : 0, width, rb_str_new2(" "));
863 num = cstr_update(&format_str, &format_str_capa, start,
864 i - start + 1, arg);
865 format_len += num;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored
866 i += num;
867 break;
868 }
869 }
cb65416 the great schism, part I
Laurent Sansonetti authored
870
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored
871 bail:
872 fmt = rb_unicode_str_new(format_str, format_len);
873 if (tainted) {
874 OBJ_TAINT(fmt);
875 }
876 return fmt;
cb65416 the great schism, part I
Laurent Sansonetti authored
877 }
Something went wrong with that request. Please try again.