1 /**********************************************************************
6 created at: Fri Oct 15 10:39:26 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "ruby/internal/config.h"
25 #include "internal/error.h"
26 #include "internal/hash.h"
27 #include "internal/numeric.h"
28 #include "internal/object.h"
29 #include "internal/sanitizers.h"
30 #include "internal/symbol.h"
31 #include "ruby/encoding.h"
33 #include "ruby/util.h"
35 #define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
37 static char *fmt_setup(char*,size_t,int,int,int,int);
38 static char *ruby_ultoa(unsigned long val
, char *endp
, int base
, int octzero
);
41 sign_bits(int base
, const char *p
)
47 if (*p
== 'X') c
= 'F';
68 #define CHECK(l) do {\
69 int cr = ENC_CODERANGE(result);\
70 while ((l) >= bsiz - blen) {\
72 if (bsiz<0) rb_raise(rb_eArgError, "too big specifier");\
74 rb_str_resize(result, bsiz);\
75 ENC_CODERANGE_SET(result, cr);\
76 buf = RSTRING_PTR(result);\
79 #define PUSH(s, l) do { \
84 #define PUSH_(s, l) do { \
85 memcpy(&buf[blen], (s), (l));\
89 #define FILL(c, l) do { \
95 #define FILL_(c, l) do { \
96 memset(&buf[blen], (c), (l));\
100 #define GETARG() (!UNDEF_P(nextvalue) ? nextvalue : \
103 #define GETNEXTARG() ( \
104 check_next_arg(posarg, nextarg), \
105 (posarg = nextarg++, GETNTHARG(posarg)))
107 #define GETPOSARG(n) ( \
108 check_pos_arg(posarg, (n)), \
109 (posarg = -1, GETNTHARG(n)))
111 #define GETNTHARG(nth) \
112 (((nth) >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[(nth)])
114 #define CHECKNAMEARG(name, len, enc) ( \
115 check_name_arg(posarg, name, len, enc), \
118 #define GETNUM(n, val) \
119 (!(p = get_num(p, end, enc, &(n))) ? \
120 rb_raise(rb_eArgError, #val " too big") : (void)0)
122 #define GETASTER(val) do { \
127 tmp = GETPOSARG(n); \
130 tmp = GETNEXTARG(); \
133 (val) = NUM2INT(tmp); \
137 get_num(const char *p
, const char *end
, rb_encoding
*enc
, int *valp
)
140 for (; p
< end
&& rb_enc_isdigit(*p
, enc
); p
++) {
141 if (MUL_OVERFLOW_INT_P(10, next_n
))
144 if (INT_MAX
- (*p
- '0') < next_n
)
149 rb_raise(rb_eArgError
, "malformed format string - %%*[0-9]");
156 check_next_arg(int posarg
, int nextarg
)
160 rb_raise(rb_eArgError
, "unnumbered(%d) mixed with numbered", nextarg
);
162 rb_raise(rb_eArgError
, "unnumbered(%d) mixed with named", nextarg
);
167 check_pos_arg(int posarg
, int n
)
170 rb_raise(rb_eArgError
, "numbered(%d) after unnumbered(%d)", n
, posarg
);
173 rb_raise(rb_eArgError
, "numbered(%d) after named", n
);
176 rb_raise(rb_eArgError
, "invalid index - %d$", n
);
181 check_name_arg(int posarg
, const char *name
, int len
, rb_encoding
*enc
)
184 rb_enc_raise(enc
, rb_eArgError
, "named%.*s after unnumbered(%d)", len
, name
, posarg
);
187 rb_enc_raise(enc
, rb_eArgError
, "named%.*s after numbered", len
, name
);
192 get_hash(volatile VALUE
*hash
, int argc
, const VALUE
*argv
)
196 if (!UNDEF_P(*hash
)) return *hash
;
198 rb_raise(rb_eArgError
, "one hash required");
200 tmp
= rb_check_hash_type(argv
[1]);
202 rb_raise(rb_eArgError
, "one hash required");
204 return (*hash
= tmp
);
208 rb_f_sprintf(int argc
, const VALUE
*argv
)
210 return rb_str_format(argc
- 1, argv
+ 1, GETNTHARG(0));
214 rb_str_format(int argc
, const VALUE
*argv
, VALUE fmt
)
216 enum {default_float_precision
= 6};
224 enum ruby_coderange_type coderange
= ENC_CODERANGE_7BIT
;
225 int width
, prec
, flags
= FNONE
;
232 volatile VALUE hash
= Qundef
;
234 #define CHECK_FOR_WIDTH(f) \
235 if ((f) & FWIDTH) { \
236 rb_raise(rb_eArgError, "width given twice"); \
238 if ((f) & FPREC0) { \
239 rb_raise(rb_eArgError, "width after precision"); \
241 #define CHECK_FOR_FLAGS(f) \
242 if ((f) & FWIDTH) { \
243 rb_raise(rb_eArgError, "flag after width"); \
245 if ((f) & FPREC0) { \
246 rb_raise(rb_eArgError, "flag after precision"); \
249 #define update_coderange(partial) do { \
250 if (coderange != ENC_CODERANGE_BROKEN && scanned < blen \
251 && rb_enc_to_index(enc) /* != ENCINDEX_ASCII_8BIT */) { \
252 int cr = coderange; \
253 scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr); \
254 ENC_CODERANGE_SET(result, \
255 (partial && cr == ENC_CODERANGE_UNKNOWN ? \
256 ENC_CODERANGE_BROKEN : (coderange = cr))); \
262 enc
= rb_enc_get(fmt
);
263 rb_must_asciicompat(fmt
);
265 fmt
= rb_str_tmp_frozen_acquire(fmt
);
266 p
= RSTRING_PTR(fmt
);
267 end
= p
+ RSTRING_LEN(fmt
);
270 result
= rb_str_buf_new(bsiz
);
271 rb_enc_associate(result
, enc
);
272 buf
= RSTRING_PTR(result
);
273 memset(buf
, 0, bsiz
);
274 ENC_CODERANGE_SET(result
, coderange
);
276 for (; p
< end
; p
++) {
281 for (t
= p
; t
< end
&& *t
!= '%'; t
++) ;
283 rb_raise(rb_eArgError
, "incomplete format specifier; use %%%% (double %%) instead");
286 update_coderange(FALSE
);
288 /* end of fmt string */
291 p
= t
+ 1; /* skip `%' */
298 if (rb_enc_isprint(*p
, enc
))
299 rb_raise(rb_eArgError
, "malformed format string - %%%c", *p
);
301 rb_raise(rb_eArgError
, "malformed format string");
305 CHECK_FOR_FLAGS(flags
);
311 CHECK_FOR_FLAGS(flags
);
317 CHECK_FOR_FLAGS(flags
);
323 CHECK_FOR_FLAGS(flags
);
329 CHECK_FOR_FLAGS(flags
);
334 case '1': case '2': case '3': case '4':
335 case '5': case '6': case '7': case '8': case '9':
339 if (!UNDEF_P(nextvalue
)) {
340 rb_raise(rb_eArgError
, "value given twice - %d$", n
);
342 nextvalue
= GETPOSARG(n
);
346 CHECK_FOR_WIDTH(flags
);
354 const char *start
= p
;
355 char term
= (*p
== '<') ? '>' : '}';
358 for (; p
< end
&& *p
!= term
; ) {
359 p
+= rb_enc_mbclen(p
, end
, enc
);
362 rb_raise(rb_eArgError
, "malformed name - unmatched parenthesis");
364 #if SIZEOF_INT < SIZEOF_SIZE_T
365 if ((size_t)(p
- start
) >= INT_MAX
) {
366 const int message_limit
= 20;
367 len
= (int)(rb_enc_right_char_head(start
, start
+ message_limit
, p
, enc
) - start
);
368 rb_enc_raise(enc
, rb_eArgError
,
369 "too long name (%"PRIuSIZE
" bytes) - %.*s...%c",
370 (size_t)(p
- start
- 2), len
, start
, term
);
373 len
= (int)(p
- start
+ 1); /* including parenthesis */
375 rb_enc_raise(enc
, rb_eArgError
, "named%.*s after <%"PRIsVALUE
">",
376 len
, start
, rb_sym2str(sym
));
378 CHECKNAMEARG(start
, len
, enc
);
379 get_hash(&hash
, argc
, argv
);
380 sym
= rb_check_symbol_cstr(start
+ 1,
381 len
- 2 /* without parenthesis */,
383 if (!NIL_P(sym
)) nextvalue
= rb_hash_lookup2(hash
, sym
, Qundef
);
384 if (UNDEF_P(nextvalue
)) {
386 sym
= rb_sym_intern(start
+ 1,
387 len
- 2 /* without parenthesis */,
390 nextvalue
= rb_hash_default_value(hash
, sym
);
391 if (NIL_P(nextvalue
)) {
392 rb_key_err_raise(rb_enc_sprintf(enc
, "key%.*s not found", len
, start
), hash
, sym
);
395 if (term
== '}') goto format_s
;
401 CHECK_FOR_WIDTH(flags
);
407 if (width
< 0) rb_raise(rb_eArgError
, "width too big");
413 if (flags
& FPREC0
) {
414 rb_raise(rb_eArgError
, "precision given twice");
416 flags
|= FPREC
|FPREC0
;
422 if (prec
< 0) { /* ignore negative precision */
429 GETNUM(prec
, precision
);
437 if (flags
!= FNONE
) {
438 rb_raise(rb_eArgError
, "invalid format character - %%");
445 VALUE val
= GETARG();
450 tmp
= rb_check_string_type(val
);
458 if (n
>= 0) n
= rb_enc_codelen((c
= n
), enc
);
460 rb_raise(rb_eArgError
, "invalid character");
462 int encidx
= rb_ascii8bit_appendable_encoding_index(enc
, c
);
463 if (encidx
>= 0 && encidx
!= rb_enc_to_index(enc
)) {
465 rb_enc_associate_index(result
, encidx
);
466 enc
= rb_enc_from_index(encidx
);
467 coderange
= ENC_CODERANGE_VALID
;
469 if (!(flags
& FWIDTH
)) {
471 rb_enc_mbcput(c
, &buf
[blen
], enc
);
474 else if ((flags
& FMINUS
)) {
476 CHECK(n
+ (width
> 0 ? width
: 0));
477 rb_enc_mbcput(c
, &buf
[blen
], enc
);
479 if (width
> 0) FILL_(' ', width
);
483 CHECK(n
+ (width
> 0 ? width
: 0));
484 if (width
> 0) FILL_(' ', width
);
485 rb_enc_mbcput(c
, &buf
[blen
], enc
);
495 VALUE arg
= GETARG();
499 str
= rb_inspect(arg
);
502 str
= rb_obj_as_string(arg
);
505 len
= RSTRING_LEN(str
);
506 rb_str_set_len(result
, blen
);
507 update_coderange(TRUE
);
508 enc
= rb_enc_check(result
, str
);
509 if (flags
&(FPREC
|FWIDTH
)) {
510 slen
= rb_enc_strlen(RSTRING_PTR(str
),RSTRING_END(str
),enc
);
512 rb_raise(rb_eArgError
, "invalid mbstring sequence");
514 if ((flags
&FPREC
) && (prec
< slen
)) {
515 char *p
= rb_enc_nth(RSTRING_PTR(str
), RSTRING_END(str
),
518 len
= p
- RSTRING_PTR(str
);
520 /* need to adjust multi-byte string pos */
521 if ((flags
&FWIDTH
) && (width
> slen
)) {
524 if (!(flags
&FMINUS
)) {
528 memcpy(&buf
[blen
], RSTRING_PTR(str
), len
);
534 rb_enc_associate(result
, enc
);
538 PUSH(RSTRING_PTR(str
), len
);
540 rb_enc_associate(result
, enc
);
553 volatile VALUE val
= GETARG();
555 char nbuf
[BIT_DIGITS(SIZEOF_LONG
*CHAR_BIT
)+2], *s
;
556 const char *prefix
= 0;
557 int sign
= 0, dots
= 0;
560 int base
, bignum
= 0;
573 if (flags
&(FPLUS
|FSPACE
)) sign
= 1;
576 if (flags
& FSHARP
) {
581 prefix
= "0x"; break;
583 prefix
= "0X"; break;
585 prefix
= "0b"; break;
587 prefix
= "0B"; break;
594 if (FIXABLE(RFLOAT_VALUE(val
))) {
595 val
= LONG2FIX((long)RFLOAT_VALUE(val
));
598 val
= rb_dbl2big(RFLOAT_VALUE(val
));
599 if (FIXNUM_P(val
)) goto bin_retry
;
603 val
= rb_str_to_inum(val
, 0, TRUE
);
612 val
= rb_Integer(val
);
633 int numbits
= ffs(base
)-1;
635 size_t numdigits
= rb_absint_numwords(val
, numbits
, &abs_nlz_bits
);
637 if (INT_MAX
-1 < numdigits
) /* INT_MAX is used because rb_long2int is used later. */
638 rb_raise(rb_eArgError
, "size too big");
642 tmp
= rb_str_new(NULL
, numdigits
);
643 valsign
= rb_integer_pack(val
, RSTRING_PTR(tmp
), RSTRING_LEN(tmp
),
644 1, CHAR_BIT
-numbits
, INTEGER_PACK_BIG_ENDIAN
);
645 for (i
= 0; i
< RSTRING_LEN(tmp
); i
++)
646 RSTRING_PTR(tmp
)[i
] = ruby_digitmap
[((unsigned char *)RSTRING_PTR(tmp
))[i
]];
647 s
= RSTRING_PTR(tmp
);
652 else if (flags
& FPLUS
) {
656 else if (flags
& FSPACE
) {
662 /* Following conditional "numdigits++" guarantees the
663 * most significant digit as
664 * - '1'(bin), '7'(oct) or 'f'(hex) for negative numbers
666 * - not '0' for positive numbers.
668 * It also guarantees the most significant two
669 * digits will not be '11'(bin), '77'(oct), 'ff'(hex)
671 if (numdigits
== 0 ||
672 ((abs_nlz_bits
!= (size_t)(numbits
-1) ||
673 !rb_absint_singlebit_p(val
)) &&
674 (!bignum
? v
< 0 : BIGNUM_NEGATIVE_P(val
))))
676 tmp
= rb_str_new(NULL
, numdigits
);
677 valsign
= rb_integer_pack(val
, RSTRING_PTR(tmp
), RSTRING_LEN(tmp
),
678 1, CHAR_BIT
-numbits
, INTEGER_PACK_2COMP
| INTEGER_PACK_BIG_ENDIAN
);
679 for (i
= 0; i
< RSTRING_LEN(tmp
); i
++)
680 RSTRING_PTR(tmp
)[i
] = ruby_digitmap
[((unsigned char *)RSTRING_PTR(tmp
))[i
]];
681 s
= RSTRING_PTR(tmp
);
684 len
= rb_long2int(RSTRING_END(tmp
) - s
);
694 else if (flags
& FPLUS
) {
698 else if (flags
& FSPACE
) {
702 s
= ruby_ultoa((unsigned long)v
, nbuf
+ sizeof(nbuf
), 10, 0);
703 len
= (int)(nbuf
+ sizeof(nbuf
) - s
);
706 tmp
= rb_big2str(val
, 10);
707 s
= RSTRING_PTR(tmp
);
715 else if (flags
& FPLUS
) {
719 else if (flags
& FSPACE
) {
723 len
= rb_long2int(RSTRING_END(tmp
) - s
);
734 while ((c
= (int)(unsigned char)*pp
) != 0) {
735 *pp
= rb_enc_toupper(c
, enc
);
739 if (prefix
&& !prefix
[1]) { /* octal */
743 else if (len
== 1 && *s
== '0') {
745 if (flags
& FPREC
) prec
--;
747 else if ((flags
& FPREC
) && (prec
> len
)) {
751 else if (len
== 1 && *s
== '0') {
755 width
-= (int)strlen(prefix
);
757 if ((flags
& (FZERO
|FMINUS
|FPREC
)) == FZERO
) {
763 if (!prefix
&& prec
== 0 && len
== 1 && *s
== '0') len
= 0;
768 if (!(flags
&FMINUS
)) {
772 if (sc
) PUSH(&sc
, 1);
774 int plen
= (int)strlen(prefix
);
777 if (dots
) PUSH("..", 2);
780 if (!sign
&& valsign
< 0) {
781 char c
= sign_bits(base
, p
);
782 FILL_(c
, prec
- len
);
784 else if ((flags
& (FMINUS
|FPREC
)) != FMINUS
) {
785 FILL_('0', prec
- len
);
796 VALUE val
= GETARG(), num
, den
;
797 int sign
= (flags
&FPLUS
) ? 1 : 0, zero
= 0;
799 if (RB_INTEGER_TYPE_P(val
)) {
803 else if (RB_TYPE_P(val
, T_RATIONAL
)) {
804 den
= rb_rational_den(val
);
805 num
= rb_rational_num(val
);
811 if (!(flags
&FPREC
)) prec
= default_float_precision
;
813 if ((SIGNED_VALUE
)num
< 0) {
814 long n
= -FIX2LONG(num
);
819 else if (BIGNUM_NEGATIVE_P(num
)) {
821 num
= rb_big_uminus(num
);
823 if (den
!= INT2FIX(1)) {
824 num
= rb_int_mul(num
, rb_int_positive_pow(10, prec
));
825 num
= rb_int_plus(num
, rb_int_idiv(den
, INT2FIX(2)));
826 num
= rb_int_idiv(num
, den
);
828 else if (prec
>= 0) {
831 val
= rb_int2str(num
, 10);
832 len
= RSTRING_LEN(val
) + zero
;
833 if (prec
>= len
) len
= prec
+ 1; /* integer part 0 */
834 if (sign
|| (flags
&FSPACE
)) ++len
;
835 if (prec
> 0) ++len
; /* period */
836 fill
= width
> len
? width
- len
: 0;
838 if (fill
&& !(flags
&(FMINUS
|FZERO
))) {
841 if (sign
|| (flags
&FSPACE
)) {
842 buf
[blen
++] = sign
> 0 ? '+' : sign
< 0 ? '-' : ' ';
844 if (fill
&& (flags
&(FMINUS
|FZERO
)) == FZERO
) {
847 len
= RSTRING_LEN(val
) + zero
;
848 t
= RSTRING_PTR(val
);
850 PUSH_(t
, len
- prec
);
861 else if (prec
> len
) {
862 FILL_('0', prec
- len
);
866 PUSH_(t
+ len
- prec
, prec
);
868 if (fill
&& (flags
&FMINUS
)) {
878 /* TODO: rational support */
883 VALUE val
= GETARG();
886 fval
= RFLOAT_VALUE(rb_Float(val
));
887 if (!isfinite(fval
)) {
899 need
= (int)strlen(expr
);
901 if (!isnan(fval
) && fval
< 0.0)
903 else if (flags
& (FPLUS
|FSPACE
))
904 sign
= (flags
& FPLUS
) ? '+' : ' ';
907 if ((flags
& FWIDTH
) && need
< width
)
911 if (flags
& FMINUS
) {
913 buf
[blen
- need
--] = sign
;
914 memcpy(&buf
[blen
- need
], expr
, elen
);
918 buf
[blen
- elen
- 1] = sign
;
919 memcpy(&buf
[blen
- elen
], expr
, elen
);
924 int cr
= ENC_CODERANGE(result
);
925 char fbuf
[2*BIT_DIGITS(SIZEOF_INT
*CHAR_BIT
)+10];
926 char *fmt
= fmt_setup(fbuf
, sizeof(fbuf
), *p
, flags
, width
, prec
);
927 rb_str_set_len(result
, blen
);
928 rb_str_catf(result
, fmt
, fval
);
929 ENC_CODERANGE_SET(result
, cr
);
930 bsiz
= rb_str_capacity(result
);
931 RSTRING_GETMEM(result
, buf
, blen
);
939 update_coderange(FALSE
);
941 rb_str_tmp_frozen_release(orig
, fmt
);
942 /* XXX - We cannot validate the number of arguments if (digit)$ style used.
944 if (posarg
>= 0 && nextarg
< argc
) {
945 const char *mesg
= "too many arguments for format string";
946 if (RTEST(ruby_debug
)) rb_raise(rb_eArgError
, "%s", mesg
);
947 if (RTEST(ruby_verbose
)) rb_warn("%s", mesg
);
949 rb_str_resize(result
, blen
);
955 fmt_setup(char *buf
, size_t size
, int c
, int flags
, int width
, int prec
)
962 buf
= ruby_ultoa(prec
, buf
, 10, 0);
966 if (flags
& FWIDTH
) {
967 buf
= ruby_ultoa(width
, buf
, 10, 0);
970 if (flags
& FSPACE
) *--buf
= ' ';
971 if (flags
& FZERO
) *--buf
= '0';
972 if (flags
& FMINUS
) *--buf
= '-';
973 if (flags
& FPLUS
) *--buf
= '+';
974 if (flags
& FSHARP
) *--buf
= '#';
980 #define FILE rb_printf_buffer
981 #define __sbuf rb_printf_sbuf
982 #define __sFILE rb_printf_sfile
987 #if SIZEOF_LONG < SIZEOF_LONG_LONG
988 # if SIZEOF_LONG_LONG == SIZEOF_VOIDP
989 /* actually this doesn't mean a pointer is strictly 64bit, but just
991 # define _HAVE_LLP64_
993 # define _HAVE_SANE_QUAD_
994 # define quad_t LONG_LONG
995 # define u_quad_t unsigned LONG_LONG
997 #define FLOATING_POINT 1
998 #define BSD__dtoa ruby_dtoa
999 #define BSD__hdtoa ruby_hdtoa
1000 #ifdef RUBY_PRI_VALUE_MARK
1001 # define PRI_EXTRA_MARK RUBY_PRI_VALUE_MARK
1003 #define lower_hexdigits (ruby_hexdigits+0)
1004 #define upper_hexdigits (ruby_hexdigits+16)
1005 #include "vsnprintf.c"
1008 ruby_ultoa(unsigned long val
, char *endp
, int base
, int flags
)
1010 const char *xdigs
= lower_hexdigits
;
1011 int octzero
= flags
& FSHARP
;
1012 return BSD__ultoa(val
, endp
, base
, octzero
, xdigs
);
1015 static int ruby_do_vsnprintf(char *str
, size_t n
, const char *fmt
, va_list ap
);
1018 ruby_vsnprintf(char *str
, size_t n
, const char *fmt
, va_list ap
)
1020 if (str
&& (ssize_t
)n
< 1)
1022 return ruby_do_vsnprintf(str
, n
, fmt
, ap
);
1026 ruby_do_vsnprintf(char *str
, size_t n
, const char *fmt
, va_list ap
)
1031 f
._flags
= __SWR
| __SSTR
;
1032 f
._bf
._base
= f
._p
= (unsigned char *)str
;
1033 f
._bf
._size
= f
._w
= str
? (n
- 1) : 0;
1034 f
.vwrite
= BSD__sfvwrite
;
1036 ret
= BSD_vfprintf(&f
, fmt
, ap
);
1038 #if SIZEOF_SIZE_T > SIZEOF_INT
1039 if (n
> INT_MAX
) return INT_MAX
;
1045 ruby_snprintf(char *str
, size_t n
, char const *fmt
, ...)
1050 if (str
&& (ssize_t
)n
< 1)
1054 ret
= ruby_do_vsnprintf(str
, n
, fmt
, ap
);
1060 rb_printf_buffer base
;
1061 volatile VALUE value
;
1062 } rb_printf_buffer_extra
;
1065 ruby__sfvwrite(register rb_printf_buffer
*fp
, register struct __suio
*uio
)
1068 VALUE result
= (VALUE
)fp
->_bf
._base
;
1069 char *buf
= (char*)fp
->_p
;
1071 long blen
= buf
- RSTRING_PTR(result
), bsiz
= fp
->_w
;
1073 if (RBASIC(result
)->klass
) {
1074 rb_raise(rb_eRuntimeError
, "rb_vsprintf reentered");
1076 if (uio
->uio_resid
== 0)
1078 #if SIZE_MAX > LONG_MAX
1079 if (uio
->uio_resid
>= LONG_MAX
)
1080 rb_raise(rb_eRuntimeError
, "too big string");
1082 len
= (long)uio
->uio_resid
;
1086 for (iov
= uio
->uio_iov
; len
> 0; ++iov
) {
1087 MEMCPY(buf
, iov
->iov_base
, char, n
= iov
->iov_len
);
1091 fp
->_p
= (unsigned char *)buf
;
1092 rb_str_set_len(result
, buf
- RSTRING_PTR(result
));
1097 ruby__sfvextra(rb_printf_buffer
*fp
, size_t valsize
, void *valp
, long *sz
, int sign
)
1099 VALUE value
, result
= (VALUE
)fp
->_bf
._base
;
1103 if (valsize
!= sizeof(VALUE
)) return 0;
1104 value
= *(VALUE
*)valp
;
1105 if (RBASIC(result
)->klass
) {
1106 rb_raise(rb_eRuntimeError
, "rb_vsprintf reentered");
1109 # define LITERAL(str) (*sz = rb_strlen_lit(str), str)
1110 /* optimize special const cases */
1112 # define LITERAL_CASE(x) case Q##x: return LITERAL(#x)
1115 LITERAL_CASE(false);
1116 # undef LITERAL_CASE
1119 value
= rb_inspect(value
);
1121 else if (SYMBOL_P(value
)) {
1122 value
= rb_sym2str(value
);
1123 if (sign
== ' ' && !rb_str_symname_p(value
)) {
1124 value
= rb_str_escape(value
);
1128 value
= rb_obj_as_string(value
);
1129 if (sign
== ' ') value
= QUOTE(value
);
1131 enc
= rb_enc_compatible(result
, value
);
1133 rb_enc_associate(result
, enc
);
1136 enc
= rb_enc_get(result
);
1137 value
= rb_str_conv_enc_opts(value
, rb_enc_get(value
), enc
,
1138 ECONV_UNDEF_REPLACE
|ECONV_INVALID_REPLACE
,
1140 *(volatile VALUE
*)valp
= value
;
1142 StringValueCStr(value
);
1143 RSTRING_GETMEM(value
, cp
, *sz
);
1144 ((rb_printf_buffer_extra
*)fp
)->value
= value
;
1149 ruby_vsprintf0(VALUE result
, char *p
, const char *fmt
, va_list ap
)
1151 rb_printf_buffer_extra buffer
;
1152 #define f buffer.base
1153 VALUE klass
= RBASIC(result
)->klass
;
1154 int coderange
= ENC_CODERANGE(result
);
1157 if (coderange
!= ENC_CODERANGE_UNKNOWN
) scanned
= p
- RSTRING_PTR(result
);
1159 f
._flags
= __SWR
| __SSTR
;
1161 f
._w
= rb_str_capacity(result
);
1162 f
._bf
._base
= (unsigned char *)result
;
1163 f
._p
= (unsigned char *)p
;
1164 RBASIC_CLEAR_CLASS(result
);
1165 f
.vwrite
= ruby__sfvwrite
;
1166 f
.vextra
= ruby__sfvextra
;
1168 BSD_vfprintf(&f
, fmt
, ap
);
1169 RBASIC_SET_CLASS_RAW(result
, klass
);
1170 p
= RSTRING_PTR(result
);
1171 long blen
= (char *)f
._p
- p
;
1172 if (scanned
< blen
) {
1173 rb_str_coderange_scan_restartable(p
+ scanned
, p
+ blen
, rb_enc_get(result
), &coderange
);
1174 ENC_CODERANGE_SET(result
, coderange
);
1176 rb_str_resize(result
, blen
);
1181 rb_enc_vsprintf(rb_encoding
*enc
, const char *fmt
, va_list ap
)
1183 const int initial_len
= 120;
1186 result
= rb_str_buf_new(initial_len
);
1188 if (rb_enc_mbminlen(enc
) > 1) {
1189 /* the implementation deeply depends on plain char */
1190 rb_raise(rb_eArgError
, "cannot construct wchar_t based encoding string: %s",
1193 rb_enc_associate(result
, enc
);
1195 ruby_vsprintf0(result
, RSTRING_PTR(result
), fmt
, ap
);
1200 rb_enc_sprintf(rb_encoding
*enc
, const char *format
, ...)
1205 va_start(ap
, format
);
1206 result
= rb_enc_vsprintf(enc
, format
, ap
);
1213 rb_vsprintf(const char *fmt
, va_list ap
)
1215 return rb_enc_vsprintf(NULL
, fmt
, ap
);
1219 rb_sprintf(const char *format
, ...)
1224 va_start(ap
, format
);
1225 result
= rb_vsprintf(format
, ap
);
1232 rb_str_vcatf(VALUE str
, const char *fmt
, va_list ap
)
1236 ruby_vsprintf0(str
, RSTRING_END(str
), fmt
, ap
);
1242 rb_str_catf(VALUE str
, const char *format
, ...)
1246 va_start(ap
, format
);
1247 str
= rb_str_vcatf(str
, format
, ap
);