Ruby  3.4.0dev (2024-11-05 revision 348a53415339076afc4a02fcd09f3ae36e9c4c61)
sprintf.c (348a53415339076afc4a02fcd09f3ae36e9c4c61)
1 /**********************************************************************
2 
3  sprintf.c -
4 
5  $Author$
6  created at: Fri Oct 15 10:39:26 JST 1993
7 
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
11 
12 **********************************************************************/
13 
14 #include "ruby/internal/config.h"
15 
16 #include <math.h>
17 #include <stdarg.h>
18 
19 #ifdef HAVE_IEEEFP_H
20 # include <ieeefp.h>
21 #endif
22 
23 #include "id.h"
24 #include "internal.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"
32 #include "ruby/re.h"
33 #include "ruby/util.h"
34 
35 #define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
36 
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);
39 
40 static char
41 sign_bits(int base, const char *p)
42 {
43  char c = '.';
44 
45  switch (base) {
46  case 16:
47  if (*p == 'X') c = 'F';
48  else c = 'f';
49  break;
50  case 8:
51  c = '7'; break;
52  case 2:
53  c = '1'; break;
54  }
55  return c;
56 }
57 
58 #define FNONE 0
59 #define FSHARP 1
60 #define FMINUS 2
61 #define FPLUS 4
62 #define FZERO 8
63 #define FSPACE 16
64 #define FWIDTH 32
65 #define FPREC 64
66 #define FPREC0 128
67 
68 #define CHECK(l) do {\
69  int cr = ENC_CODERANGE(result);\
70  while ((l) >= bsiz - blen) {\
71  bsiz*=2;\
72  if (bsiz<0) rb_raise(rb_eArgError, "too big specifier");\
73  }\
74  rb_str_resize(result, bsiz);\
75  ENC_CODERANGE_SET(result, cr);\
76  buf = RSTRING_PTR(result);\
77 } while (0)
78 
79 #define PUSH(s, l) do { \
80  CHECK(l);\
81  PUSH_(s, l);\
82 } while (0)
83 
84 #define PUSH_(s, l) do { \
85  memcpy(&buf[blen], (s), (l));\
86  blen += (l);\
87 } while (0)
88 
89 #define FILL(c, l) do { \
90  if ((l) <= 0) break;\
91  CHECK(l);\
92  FILL_(c, l);\
93 } while (0)
94 
95 #define FILL_(c, l) do { \
96  memset(&buf[blen], (c), (l));\
97  blen += (l);\
98 } while (0)
99 
100 #define GETARG() (!UNDEF_P(nextvalue) ? nextvalue : \
101  GETNEXTARG())
102 
103 #define GETNEXTARG() ( \
104  check_next_arg(posarg, nextarg), \
105  (posarg = nextarg++, GETNTHARG(posarg)))
106 
107 #define GETPOSARG(n) ( \
108  check_pos_arg(posarg, (n)), \
109  (posarg = -1, GETNTHARG(n)))
110 
111 #define GETNTHARG(nth) \
112  (((nth) >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[(nth)])
113 
114 #define CHECKNAMEARG(name, len, enc) ( \
115  check_name_arg(posarg, name, len, enc), \
116  posarg = -2)
117 
118 #define GETNUM(n, val) \
119  (!(p = get_num(p, end, enc, &(n))) ? \
120  rb_raise(rb_eArgError, #val " too big") : (void)0)
121 
122 #define GETASTER(val) do { \
123  t = p++; \
124  n = 0; \
125  GETNUM(n, val); \
126  if (*p == '$') { \
127  tmp = GETPOSARG(n); \
128  } \
129  else { \
130  tmp = GETNEXTARG(); \
131  p = t; \
132  } \
133  (val) = NUM2INT(tmp); \
134 } while (0)
135 
136 static const char *
137 get_num(const char *p, const char *end, rb_encoding *enc, int *valp)
138 {
139  int next_n = *valp;
140  for (; p < end && rb_enc_isdigit(*p, enc); p++) {
141  if (MUL_OVERFLOW_INT_P(10, next_n))
142  return NULL;
143  next_n *= 10;
144  if (INT_MAX - (*p - '0') < next_n)
145  return NULL;
146  next_n += *p - '0';
147  }
148  if (p >= end) {
149  rb_raise(rb_eArgError, "malformed format string - %%*[0-9]");
150  }
151  *valp = next_n;
152  return p;
153 }
154 
155 static void
156 check_next_arg(int posarg, int nextarg)
157 {
158  switch (posarg) {
159  case -1:
160  rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg);
161  case -2:
162  rb_raise(rb_eArgError, "unnumbered(%d) mixed with named", nextarg);
163  }
164 }
165 
166 static void
167 check_pos_arg(int posarg, int n)
168 {
169  if (posarg > 0) {
170  rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n, posarg);
171  }
172  if (posarg == -2) {
173  rb_raise(rb_eArgError, "numbered(%d) after named", n);
174  }
175  if (n < 1) {
176  rb_raise(rb_eArgError, "invalid index - %d$", n);
177  }
178 }
179 
180 static void
181 check_name_arg(int posarg, const char *name, int len, rb_encoding *enc)
182 {
183  if (posarg > 0) {
184  rb_enc_raise(enc, rb_eArgError, "named%.*s after unnumbered(%d)", len, name, posarg);
185  }
186  if (posarg == -1) {
187  rb_enc_raise(enc, rb_eArgError, "named%.*s after numbered", len, name);
188  }
189 }
190 
191 static VALUE
192 get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
193 {
194  VALUE tmp;
195 
196  if (!UNDEF_P(*hash)) return *hash;
197  if (argc != 2) {
198  rb_raise(rb_eArgError, "one hash required");
199  }
200  tmp = rb_check_hash_type(argv[1]);
201  if (NIL_P(tmp)) {
202  rb_raise(rb_eArgError, "one hash required");
203  }
204  return (*hash = tmp);
205 }
206 
207 VALUE
208 rb_f_sprintf(int argc, const VALUE *argv)
209 {
210  return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
211 }
212 
213 VALUE
214 rb_str_format(int argc, const VALUE *argv, VALUE fmt)
215 {
216  enum {default_float_precision = 6};
217  rb_encoding *enc;
218  const char *p, *end;
219  char *buf;
220  long blen, bsiz;
221  VALUE result;
222 
223  long scanned = 0;
224  enum ruby_coderange_type coderange = ENC_CODERANGE_7BIT;
225  int width, prec, flags = FNONE;
226  int nextarg = 1;
227  int posarg = 0;
228  VALUE nextvalue;
229  VALUE tmp;
230  VALUE orig;
231  VALUE str;
232  volatile VALUE hash = Qundef;
233 
234 #define CHECK_FOR_WIDTH(f) \
235  if ((f) & FWIDTH) { \
236  rb_raise(rb_eArgError, "width given twice"); \
237  } \
238  if ((f) & FPREC0) { \
239  rb_raise(rb_eArgError, "width after precision"); \
240  }
241 #define CHECK_FOR_FLAGS(f) \
242  if ((f) & FWIDTH) { \
243  rb_raise(rb_eArgError, "flag after width"); \
244  } \
245  if ((f) & FPREC0) { \
246  rb_raise(rb_eArgError, "flag after precision"); \
247  }
248 
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))); \
257  } \
258  } while (0)
259  ++argc;
260  --argv;
261  StringValue(fmt);
262  enc = rb_enc_get(fmt);
263  rb_must_asciicompat(fmt);
264  orig = fmt;
265  fmt = rb_str_tmp_frozen_acquire(fmt);
266  p = RSTRING_PTR(fmt);
267  end = p + RSTRING_LEN(fmt);
268  blen = 0;
269  bsiz = 120;
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);
275 
276  for (; p < end; p++) {
277  const char *t;
278  int n;
279  VALUE sym = Qnil;
280 
281  for (t = p; t < end && *t != '%'; t++) ;
282  if (t + 1 == end) {
283  rb_raise(rb_eArgError, "incomplete format specifier; use %%%% (double %%) instead");
284  }
285  PUSH(p, t - p);
286  update_coderange(FALSE);
287  if (t >= end) {
288  /* end of fmt string */
289  goto sprint_exit;
290  }
291  p = t + 1; /* skip `%' */
292 
293  width = prec = -1;
294  nextvalue = Qundef;
295  retry:
296  switch (*p) {
297  default:
298  if (rb_enc_isprint(*p, enc))
299  rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
300  else
301  rb_raise(rb_eArgError, "malformed format string");
302  break;
303 
304  case ' ':
305  CHECK_FOR_FLAGS(flags);
306  flags |= FSPACE;
307  p++;
308  goto retry;
309 
310  case '#':
311  CHECK_FOR_FLAGS(flags);
312  flags |= FSHARP;
313  p++;
314  goto retry;
315 
316  case '+':
317  CHECK_FOR_FLAGS(flags);
318  flags |= FPLUS;
319  p++;
320  goto retry;
321 
322  case '-':
323  CHECK_FOR_FLAGS(flags);
324  flags |= FMINUS;
325  p++;
326  goto retry;
327 
328  case '0':
329  CHECK_FOR_FLAGS(flags);
330  flags |= FZERO;
331  p++;
332  goto retry;
333 
334  case '1': case '2': case '3': case '4':
335  case '5': case '6': case '7': case '8': case '9':
336  n = 0;
337  GETNUM(n, width);
338  if (*p == '$') {
339  if (!UNDEF_P(nextvalue)) {
340  rb_raise(rb_eArgError, "value given twice - %d$", n);
341  }
342  nextvalue = GETPOSARG(n);
343  p++;
344  goto retry;
345  }
346  CHECK_FOR_WIDTH(flags);
347  width = n;
348  flags |= FWIDTH;
349  goto retry;
350 
351  case '<':
352  case '{':
353  {
354  const char *start = p;
355  char term = (*p == '<') ? '>' : '}';
356  int len;
357 
358  for (; p < end && *p != term; ) {
359  p += rb_enc_mbclen(p, end, enc);
360  }
361  if (p >= end) {
362  rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
363  }
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);
369  "too long name (%"PRIuSIZE" bytes) - %.*s...%c",
370  (size_t)(p - start - 2), len, start, term);
371  }
372 #endif
373  len = (int)(p - start + 1); /* including parenthesis */
374  if (sym != Qnil) {
375  rb_enc_raise(enc, rb_eArgError, "named%.*s after <%"PRIsVALUE">",
376  len, start, rb_sym2str(sym));
377  }
378  CHECKNAMEARG(start, len, enc);
379  get_hash(&hash, argc, argv);
380  sym = rb_check_symbol_cstr(start + 1,
381  len - 2 /* without parenthesis */,
382  enc);
383  if (!NIL_P(sym)) nextvalue = rb_hash_lookup2(hash, sym, Qundef);
384  if (UNDEF_P(nextvalue)) {
385  if (NIL_P(sym)) {
386  sym = rb_sym_intern(start + 1,
387  len - 2 /* without parenthesis */,
388  enc);
389  }
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);
393  }
394  }
395  if (term == '}') goto format_s;
396  p++;
397  goto retry;
398  }
399 
400  case '*':
401  CHECK_FOR_WIDTH(flags);
402  flags |= FWIDTH;
403  GETASTER(width);
404  if (width < 0) {
405  flags |= FMINUS;
406  width = -width;
407  if (width < 0) rb_raise(rb_eArgError, "width too big");
408  }
409  p++;
410  goto retry;
411 
412  case '.':
413  if (flags & FPREC0) {
414  rb_raise(rb_eArgError, "precision given twice");
415  }
416  flags |= FPREC|FPREC0;
417 
418  prec = 0;
419  p++;
420  if (*p == '*') {
421  GETASTER(prec);
422  if (prec < 0) { /* ignore negative precision */
423  flags &= ~FPREC;
424  }
425  p++;
426  goto retry;
427  }
428 
429  GETNUM(prec, precision);
430  goto retry;
431 
432  case '%':
433  if (flags != FNONE) {
434  rb_raise(rb_eArgError, "invalid format character - %%");
435  }
436  PUSH("%", 1);
437  break;
438 
439  case 'c':
440  {
441  VALUE val = GETARG();
442  VALUE tmp;
443  unsigned int c;
444  int n;
445 
446  tmp = rb_check_string_type(val);
447  if (!NIL_P(tmp)) {
448  flags |= FPREC;
449  prec = 1;
450  str = tmp;
451  goto format_s1;
452  }
453  n = NUM2INT(val);
454  if (n >= 0) n = rb_enc_codelen((c = n), enc);
455  if (n <= 0) {
456  rb_raise(rb_eArgError, "invalid character");
457  }
458  int encidx = rb_ascii8bit_appendable_encoding_index(enc, c);
459  if (encidx >= 0 && encidx != rb_enc_to_index(enc)) {
460  /* special case */
461  rb_enc_associate_index(result, encidx);
462  enc = rb_enc_from_index(encidx);
463  coderange = ENC_CODERANGE_VALID;
464  }
465  if (!(flags & FWIDTH)) {
466  CHECK(n);
467  rb_enc_mbcput(c, &buf[blen], enc);
468  blen += n;
469  }
470  else if ((flags & FMINUS)) {
471  --width;
472  CHECK(n + (width > 0 ? width : 0));
473  rb_enc_mbcput(c, &buf[blen], enc);
474  blen += n;
475  if (width > 0) FILL_(' ', width);
476  }
477  else {
478  --width;
479  CHECK(n + (width > 0 ? width : 0));
480  if (width > 0) FILL_(' ', width);
481  rb_enc_mbcput(c, &buf[blen], enc);
482  blen += n;
483  }
484  }
485  break;
486 
487  case 's':
488  case 'p':
489  format_s:
490  {
491  VALUE arg = GETARG();
492  long len, slen;
493 
494  if (*p == 'p') {
495  str = rb_inspect(arg);
496  }
497  else {
498  str = rb_obj_as_string(arg);
499  }
500  format_s1:
501  len = RSTRING_LEN(str);
502  rb_str_set_len(result, blen);
503  update_coderange(TRUE);
504  enc = rb_enc_check(result, str);
505  if (flags&(FPREC|FWIDTH)) {
506  slen = rb_enc_strlen(RSTRING_PTR(str),RSTRING_END(str),enc);
507  if (slen < 0) {
508  rb_raise(rb_eArgError, "invalid mbstring sequence");
509  }
510  if ((flags&FPREC) && (prec < slen)) {
511  char *p = rb_enc_nth(RSTRING_PTR(str), RSTRING_END(str),
512  prec, enc);
513  slen = prec;
514  len = p - RSTRING_PTR(str);
515  }
516  /* need to adjust multi-byte string pos */
517  if ((flags&FWIDTH) && (width > slen)) {
518  width -= (int)slen;
519  CHECK(len + width);
520  if (!(flags&FMINUS)) {
521  FILL_(' ', width);
522  width = 0;
523  }
524  memcpy(&buf[blen], RSTRING_PTR(str), len);
525  RB_GC_GUARD(str);
526  blen += len;
527  if (flags&FMINUS) {
528  FILL_(' ', width);
529  }
530  rb_enc_associate(result, enc);
531  break;
532  }
533  }
534  PUSH(RSTRING_PTR(str), len);
535  RB_GC_GUARD(str);
536  rb_enc_associate(result, enc);
537  }
538  break;
539 
540  case 'd':
541  case 'i':
542  case 'o':
543  case 'x':
544  case 'X':
545  case 'b':
546  case 'B':
547  case 'u':
548  {
549  volatile VALUE val = GETARG();
550  int valsign;
551  char nbuf[BIT_DIGITS(SIZEOF_LONG*CHAR_BIT)+2], *s;
552  const char *prefix = 0;
553  int sign = 0, dots = 0;
554  char sc = 0;
555  long v = 0;
556  int base, bignum = 0;
557  int len;
558 
559  switch (*p) {
560  case 'd':
561  case 'i':
562  case 'u':
563  sign = 1; break;
564  case 'o':
565  case 'x':
566  case 'X':
567  case 'b':
568  case 'B':
569  if (flags&(FPLUS|FSPACE)) sign = 1;
570  break;
571  }
572  if (flags & FSHARP) {
573  switch (*p) {
574  case 'o':
575  prefix = "0"; break;
576  case 'x':
577  prefix = "0x"; break;
578  case 'X':
579  prefix = "0X"; break;
580  case 'b':
581  prefix = "0b"; break;
582  case 'B':
583  prefix = "0B"; break;
584  }
585  }
586 
587  bin_retry:
588  switch (TYPE(val)) {
589  case T_FLOAT:
590  if (FIXABLE(RFLOAT_VALUE(val))) {
591  val = LONG2FIX((long)RFLOAT_VALUE(val));
592  goto bin_retry;
593  }
594  val = rb_dbl2big(RFLOAT_VALUE(val));
595  if (FIXNUM_P(val)) goto bin_retry;
596  bignum = 1;
597  break;
598  case T_STRING:
599  val = rb_str_to_inum(val, 0, TRUE);
600  goto bin_retry;
601  case T_BIGNUM:
602  bignum = 1;
603  break;
604  case T_FIXNUM:
605  v = FIX2LONG(val);
606  break;
607  default:
608  val = rb_Integer(val);
609  goto bin_retry;
610  }
611 
612  switch (*p) {
613  case 'o':
614  base = 8; break;
615  case 'x':
616  case 'X':
617  base = 16; break;
618  case 'b':
619  case 'B':
620  base = 2; break;
621  case 'u':
622  case 'd':
623  case 'i':
624  default:
625  base = 10; break;
626  }
627 
628  if (base != 10) {
629  int numbits = ffs(base)-1;
630  size_t abs_nlz_bits;
631  size_t numdigits = rb_absint_numwords(val, numbits, &abs_nlz_bits);
632  long i;
633  if (INT_MAX-1 < numdigits) /* INT_MAX is used because rb_long2int is used later. */
634  rb_raise(rb_eArgError, "size too big");
635  if (sign) {
636  if (numdigits == 0)
637  numdigits = 1;
638  tmp = rb_str_new(NULL, numdigits);
639  valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
640  1, CHAR_BIT-numbits, INTEGER_PACK_BIG_ENDIAN);
641  for (i = 0; i < RSTRING_LEN(tmp); i++)
642  RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
643  s = RSTRING_PTR(tmp);
644  if (valsign < 0) {
645  sc = '-';
646  width--;
647  }
648  else if (flags & FPLUS) {
649  sc = '+';
650  width--;
651  }
652  else if (flags & FSPACE) {
653  sc = ' ';
654  width--;
655  }
656  }
657  else {
658  /* Following conditional "numdigits++" guarantees the
659  * most significant digit as
660  * - '1'(bin), '7'(oct) or 'f'(hex) for negative numbers
661  * - '0' for zero
662  * - not '0' for positive numbers.
663  *
664  * It also guarantees the most significant two
665  * digits will not be '11'(bin), '77'(oct), 'ff'(hex)
666  * or '00'. */
667  if (numdigits == 0 ||
668  ((abs_nlz_bits != (size_t)(numbits-1) ||
669  !rb_absint_singlebit_p(val)) &&
670  (!bignum ? v < 0 : BIGNUM_NEGATIVE_P(val))))
671  numdigits++;
672  tmp = rb_str_new(NULL, numdigits);
673  valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
674  1, CHAR_BIT-numbits, INTEGER_PACK_2COMP | INTEGER_PACK_BIG_ENDIAN);
675  for (i = 0; i < RSTRING_LEN(tmp); i++)
676  RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
677  s = RSTRING_PTR(tmp);
678  dots = valsign < 0;
679  }
680  len = rb_long2int(RSTRING_END(tmp) - s);
681  }
682  else if (!bignum) {
683  valsign = 1;
684  if (v < 0) {
685  v = -v;
686  sc = '-';
687  width--;
688  valsign = -1;
689  }
690  else if (flags & FPLUS) {
691  sc = '+';
692  width--;
693  }
694  else if (flags & FSPACE) {
695  sc = ' ';
696  width--;
697  }
698  s = ruby_ultoa((unsigned long)v, nbuf + sizeof(nbuf), 10, 0);
699  len = (int)(nbuf + sizeof(nbuf) - s);
700  }
701  else {
702  tmp = rb_big2str(val, 10);
703  s = RSTRING_PTR(tmp);
704  valsign = 1;
705  if (s[0] == '-') {
706  s++;
707  sc = '-';
708  width--;
709  valsign = -1;
710  }
711  else if (flags & FPLUS) {
712  sc = '+';
713  width--;
714  }
715  else if (flags & FSPACE) {
716  sc = ' ';
717  width--;
718  }
719  len = rb_long2int(RSTRING_END(tmp) - s);
720  }
721 
722  if (dots) {
723  prec -= 2;
724  width -= 2;
725  }
726 
727  if (*p == 'X') {
728  char *pp = s;
729  int c;
730  while ((c = (int)(unsigned char)*pp) != 0) {
731  *pp = rb_enc_toupper(c, enc);
732  pp++;
733  }
734  }
735  if (prefix && !prefix[1]) { /* octal */
736  if (dots) {
737  prefix = 0;
738  }
739  else if (len == 1 && *s == '0') {
740  len = 0;
741  if (flags & FPREC) prec--;
742  }
743  else if ((flags & FPREC) && (prec > len)) {
744  prefix = 0;
745  }
746  }
747  else if (len == 1 && *s == '0') {
748  prefix = 0;
749  }
750  if (prefix) {
751  width -= (int)strlen(prefix);
752  }
753  if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
754  prec = width;
755  width = 0;
756  }
757  else {
758  if (prec < len) {
759  if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
760  prec = len;
761  }
762  width -= prec;
763  }
764  if (!(flags&FMINUS)) {
765  FILL(' ', width);
766  width = 0;
767  }
768  if (sc) PUSH(&sc, 1);
769  if (prefix) {
770  int plen = (int)strlen(prefix);
771  PUSH(prefix, plen);
772  }
773  if (dots) PUSH("..", 2);
774  if (prec > len) {
775  CHECK(prec - len);
776  if (!sign && valsign < 0) {
777  char c = sign_bits(base, p);
778  FILL_(c, prec - len);
779  }
780  else if ((flags & (FMINUS|FPREC)) != FMINUS) {
781  FILL_('0', prec - len);
782  }
783  }
784  PUSH(s, len);
785  RB_GC_GUARD(tmp);
786  FILL(' ', width);
787  }
788  break;
789 
790  case 'f':
791  {
792  VALUE val = GETARG(), num, den;
793  int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
794  long len, fill;
795  if (RB_INTEGER_TYPE_P(val)) {
796  den = INT2FIX(1);
797  num = val;
798  }
799  else if (RB_TYPE_P(val, T_RATIONAL)) {
800  den = rb_rational_den(val);
801  num = rb_rational_num(val);
802  }
803  else {
804  nextvalue = val;
805  goto float_value;
806  }
807  if (!(flags&FPREC)) prec = default_float_precision;
808  if (FIXNUM_P(num)) {
809  if ((SIGNED_VALUE)num < 0) {
810  long n = -FIX2LONG(num);
811  num = LONG2FIX(n);
812  sign = -1;
813  }
814  }
815  else if (BIGNUM_NEGATIVE_P(num)) {
816  sign = -1;
817  num = rb_big_uminus(num);
818  }
819  if (den != INT2FIX(1)) {
820  num = rb_int_mul(num, rb_int_positive_pow(10, prec));
821  num = rb_int_plus(num, rb_int_idiv(den, INT2FIX(2)));
822  num = rb_int_idiv(num, den);
823  }
824  else if (prec >= 0) {
825  zero = prec;
826  }
827  val = rb_int2str(num, 10);
828  len = RSTRING_LEN(val) + zero;
829  if (prec >= len) len = prec + 1; /* integer part 0 */
830  if (sign || (flags&FSPACE)) ++len;
831  if (prec > 0) ++len; /* period */
832  fill = width > len ? width - len : 0;
833  CHECK(fill + len);
834  if (fill && !(flags&(FMINUS|FZERO))) {
835  FILL_(' ', fill);
836  }
837  if (sign || (flags&FSPACE)) {
838  buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
839  }
840  if (fill && (flags&(FMINUS|FZERO)) == FZERO) {
841  FILL_('0', fill);
842  }
843  len = RSTRING_LEN(val) + zero;
844  t = RSTRING_PTR(val);
845  if (len > prec) {
846  PUSH_(t, len - prec);
847  }
848  else {
849  buf[blen++] = '0';
850  }
851  if (prec > 0) {
852  buf[blen++] = '.';
853  }
854  if (zero) {
855  FILL_('0', zero);
856  }
857  else if (prec > len) {
858  FILL_('0', prec - len);
859  PUSH_(t, len);
860  }
861  else if (prec > 0) {
862  PUSH_(t + len - prec, prec);
863  }
864  if (fill && (flags&FMINUS)) {
865  FILL_(' ', fill);
866  }
867  RB_GC_GUARD(val);
868  break;
869  }
870  case 'g':
871  case 'G':
872  case 'e':
873  case 'E':
874  /* TODO: rational support */
875  case 'a':
876  case 'A':
877  float_value:
878  {
879  VALUE val = GETARG();
880  double fval;
881 
882  fval = RFLOAT_VALUE(rb_Float(val));
883  if (!isfinite(fval)) {
884  const char *expr;
885  int need;
886  int elen;
887  char sign = '\0';
888 
889  if (isnan(fval)) {
890  expr = "NaN";
891  }
892  else {
893  expr = "Inf";
894  }
895  need = (int)strlen(expr);
896  elen = need;
897  if (!isnan(fval) && fval < 0.0)
898  sign = '-';
899  else if (flags & (FPLUS|FSPACE))
900  sign = (flags & FPLUS) ? '+' : ' ';
901  if (sign)
902  ++need;
903  if ((flags & FWIDTH) && need < width)
904  need = width;
905 
906  FILL(' ', need);
907  if (flags & FMINUS) {
908  if (sign)
909  buf[blen - need--] = sign;
910  memcpy(&buf[blen - need], expr, elen);
911  }
912  else {
913  if (sign)
914  buf[blen - elen - 1] = sign;
915  memcpy(&buf[blen - elen], expr, elen);
916  }
917  break;
918  }
919  else {
920  int cr = ENC_CODERANGE(result);
921  char fbuf[2*BIT_DIGITS(SIZEOF_INT*CHAR_BIT)+10];
922  char *fmt = fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
923  rb_str_set_len(result, blen);
924  rb_str_catf(result, fmt, fval);
925  ENC_CODERANGE_SET(result, cr);
926  bsiz = rb_str_capacity(result);
927  RSTRING_GETMEM(result, buf, blen);
928  }
929  }
930  break;
931  }
932  flags = FNONE;
933  }
934 
935  update_coderange(FALSE);
936  sprint_exit:
937  rb_str_tmp_frozen_release(orig, fmt);
938  /* XXX - We cannot validate the number of arguments if (digit)$ style used.
939  */
940  if (posarg >= 0 && nextarg < argc && !(argc == 2 && RB_TYPE_P(argv[1], T_HASH))) {
941  const char *mesg = "too many arguments for format string";
942  if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg);
943  if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
944  }
945  rb_str_resize(result, blen);
946 
947  return result;
948 }
949 
950 static char *
951 fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
952 {
953  buf += size;
954  *--buf = '\0';
955  *--buf = c;
956 
957  if (flags & FPREC) {
958  buf = ruby_ultoa(prec, buf, 10, 0);
959  *--buf = '.';
960  }
961 
962  if (flags & FWIDTH) {
963  buf = ruby_ultoa(width, buf, 10, 0);
964  }
965 
966  if (flags & FSPACE) *--buf = ' ';
967  if (flags & FZERO) *--buf = '0';
968  if (flags & FMINUS) *--buf = '-';
969  if (flags & FPLUS) *--buf = '+';
970  if (flags & FSHARP) *--buf = '#';
971  *--buf = '%';
972  return buf;
973 }
974 
975 #undef FILE
976 #define FILE rb_printf_buffer
977 #define __sbuf rb_printf_sbuf
978 #define __sFILE rb_printf_sfile
979 #undef feof
980 #undef ferror
981 #undef clearerr
982 #undef fileno
983 #if SIZEOF_LONG < SIZEOF_LONG_LONG
984 # if SIZEOF_LONG_LONG == SIZEOF_VOIDP
985 /* actually this doesn't mean a pointer is strictly 64bit, but just
986  * quad_t size */
987 # define _HAVE_LLP64_
988 # endif
989 # define _HAVE_SANE_QUAD_
990 # define quad_t LONG_LONG
991 # define u_quad_t unsigned LONG_LONG
992 #endif
993 #define FLOATING_POINT 1
994 #define BSD__dtoa ruby_dtoa
995 #define BSD__hdtoa ruby_hdtoa
996 #ifdef RUBY_PRI_VALUE_MARK
997 # define PRI_EXTRA_MARK RUBY_PRI_VALUE_MARK
998 #endif
999 #define lower_hexdigits (ruby_hexdigits+0)
1000 #define upper_hexdigits (ruby_hexdigits+16)
1001 #include "vsnprintf.c"
1002 
1003 static char *
1004 ruby_ultoa(unsigned long val, char *endp, int base, int flags)
1005 {
1006  const char *xdigs = lower_hexdigits;
1007  int octzero = flags & FSHARP;
1008  return BSD__ultoa(val, endp, base, octzero, xdigs);
1009 }
1010 
1011 static int ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
1012 
1013 int
1014 ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
1015 {
1016  if (str && (ssize_t)n < 1)
1017  return (EOF);
1018  return ruby_do_vsnprintf(str, n, fmt, ap);
1019 }
1020 
1021 static int
1022 ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
1023 {
1024  ssize_t ret;
1025  rb_printf_buffer f;
1026 
1027  f._flags = __SWR | __SSTR;
1028  f._bf._base = f._p = (unsigned char *)str;
1029  f._bf._size = f._w = str ? (n - 1) : 0;
1030  f.vwrite = BSD__sfvwrite;
1031  f.vextra = 0;
1032  ret = BSD_vfprintf(&f, fmt, ap);
1033  if (str) *f._p = 0;
1034 #if SIZEOF_SIZE_T > SIZEOF_INT
1035  if (n > INT_MAX) return INT_MAX;
1036 #endif
1037  return (int)ret;
1038 }
1039 
1040 int
1041 ruby_snprintf(char *str, size_t n, char const *fmt, ...)
1042 {
1043  int ret;
1044  va_list ap;
1045 
1046  if (str && (ssize_t)n < 1)
1047  return (EOF);
1048 
1049  va_start(ap, fmt);
1050  ret = ruby_do_vsnprintf(str, n, fmt, ap);
1051  va_end(ap);
1052  return ret;
1053 }
1054 
1055 typedef struct {
1056  rb_printf_buffer base;
1057  volatile VALUE value;
1059 
1060 static int
1061 ruby__sfvwrite(register rb_printf_buffer *fp, register struct __suio *uio)
1062 {
1063  struct __siov *iov;
1064  VALUE result = (VALUE)fp->_bf._base;
1065  char *buf = (char*)fp->_p;
1066  long len, n;
1067  long blen = buf - RSTRING_PTR(result), bsiz = fp->_w;
1068 
1069  if (RBASIC(result)->klass) {
1070  rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
1071  }
1072  if (uio->uio_resid == 0)
1073  return 0;
1074 #if SIZE_MAX > LONG_MAX
1075  if (uio->uio_resid >= LONG_MAX)
1076  rb_raise(rb_eRuntimeError, "too big string");
1077 #endif
1078  len = (long)uio->uio_resid;
1079  CHECK(len);
1080  buf += blen;
1081  fp->_w = bsiz;
1082  for (iov = uio->uio_iov; len > 0; ++iov) {
1083  MEMCPY(buf, iov->iov_base, char, n = iov->iov_len);
1084  buf += n;
1085  len -= n;
1086  }
1087  fp->_p = (unsigned char *)buf;
1088  rb_str_set_len(result, buf - RSTRING_PTR(result));
1089  return 0;
1090 }
1091 
1092 static const char *
1093 ruby__sfvextra(rb_printf_buffer *fp, size_t valsize, void *valp, long *sz, int sign)
1094 {
1095  VALUE value, result = (VALUE)fp->_bf._base;
1096  rb_encoding *enc;
1097  char *cp;
1098 
1099  if (valsize != sizeof(VALUE)) return 0;
1100  value = *(VALUE *)valp;
1101  if (RBASIC(result)->klass) {
1102  rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
1103  }
1104  if (sign == '+') {
1105 # define LITERAL(str) (*sz = rb_strlen_lit(str), str)
1106  /* optimize special const cases */
1107  switch (value) {
1108 # define LITERAL_CASE(x) case Q##x: return LITERAL(#x)
1109  LITERAL_CASE(nil);
1110  LITERAL_CASE(true);
1111  LITERAL_CASE(false);
1112 # undef LITERAL_CASE
1113  }
1114 # undef LITERAL
1115  value = rb_inspect(value);
1116  }
1117  else if (SYMBOL_P(value)) {
1118  value = rb_sym2str(value);
1119  if (sign == ' ' && !rb_str_symname_p(value)) {
1120  value = rb_str_escape(value);
1121  }
1122  }
1123  else {
1124  value = rb_obj_as_string(value);
1125  if (sign == ' ') value = QUOTE(value);
1126  }
1127  enc = rb_enc_compatible(result, value);
1128  if (enc) {
1129  rb_enc_associate(result, enc);
1130  }
1131  else {
1132  enc = rb_enc_get(result);
1133  value = rb_str_conv_enc_opts(value, rb_enc_get(value), enc,
1135  Qnil);
1136  *(volatile VALUE *)valp = value;
1137  }
1138  StringValueCStr(value);
1139  RSTRING_GETMEM(value, cp, *sz);
1140  ((rb_printf_buffer_extra *)fp)->value = value;
1141  return cp;
1142 }
1143 
1144 static void
1145 ruby_vsprintf0(VALUE result, char *p, const char *fmt, va_list ap)
1146 {
1147  rb_printf_buffer_extra buffer;
1148 #define f buffer.base
1149  VALUE klass = RBASIC(result)->klass;
1150  int coderange = ENC_CODERANGE(result);
1151  long scanned = 0;
1152 
1153  if (coderange != ENC_CODERANGE_UNKNOWN) scanned = p - RSTRING_PTR(result);
1154 
1155  f._flags = __SWR | __SSTR;
1156  f._bf._size = 0;
1157  f._w = rb_str_capacity(result);
1158  f._bf._base = (unsigned char *)result;
1159  f._p = (unsigned char *)p;
1160  RBASIC_CLEAR_CLASS(result);
1161  f.vwrite = ruby__sfvwrite;
1162  f.vextra = ruby__sfvextra;
1163  buffer.value = 0;
1164  BSD_vfprintf(&f, fmt, ap);
1165  RBASIC_SET_CLASS_RAW(result, klass);
1166  p = RSTRING_PTR(result);
1167  long blen = (char *)f._p - p;
1168 
1169  coderange = ENC_CODERANGE(result);
1170  if (coderange != ENC_CODERANGE_UNKNOWN && scanned < blen) {
1171  rb_str_coderange_scan_restartable(p + scanned, p + blen, rb_enc_get(result), &coderange);
1172  ENC_CODERANGE_SET(result, coderange);
1173  }
1174  rb_str_resize(result, blen);
1175 #undef f
1176 }
1177 
1178 VALUE
1179 rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
1180 {
1181  const int initial_len = 120;
1182  VALUE result;
1183 
1184  result = rb_str_buf_new(initial_len);
1185  if (enc) {
1186  if (rb_enc_mbminlen(enc) > 1) {
1187  /* the implementation deeply depends on plain char */
1188  rb_raise(rb_eArgError, "cannot construct wchar_t based encoding string: %s",
1189  rb_enc_name(enc));
1190  }
1191  rb_enc_associate(result, enc);
1192  }
1193  ruby_vsprintf0(result, RSTRING_PTR(result), fmt, ap);
1194  return result;
1195 }
1196 
1197 VALUE
1198 rb_enc_sprintf(rb_encoding *enc, const char *format, ...)
1199 {
1200  VALUE result;
1201  va_list ap;
1202 
1203  va_start(ap, format);
1204  result = rb_enc_vsprintf(enc, format, ap);
1205  va_end(ap);
1206 
1207  return result;
1208 }
1209 
1210 VALUE
1211 rb_vsprintf(const char *fmt, va_list ap)
1212 {
1213  return rb_enc_vsprintf(NULL, fmt, ap);
1214 }
1215 
1216 VALUE
1217 rb_sprintf(const char *format, ...)
1218 {
1219  VALUE result;
1220  va_list ap;
1221 
1222  va_start(ap, format);
1223  result = rb_vsprintf(format, ap);
1224  va_end(ap);
1225 
1226  return result;
1227 }
1228 
1229 VALUE
1230 rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
1231 {
1232  StringValue(str);
1233  rb_str_modify(str);
1234  ruby_vsprintf0(str, RSTRING_END(str), fmt, ap);
1235 
1236  return str;
1237 }
1238 
1239 VALUE
1240 rb_str_catf(VALUE str, const char *format, ...)
1241 {
1242  va_list ap;
1243 
1244  va_start(ap, format);
1245  str = rb_str_vcatf(str, format, ap);
1246  va_end(ap);
1247 
1248  return str;
1249 }
ruby_coderange_type
What rb_enc_str_coderange() returns.
Definition: coderange.h:33
static bool rb_enc_isprint(OnigCodePoint c, rb_encoding *enc)
Identical to rb_isprint(), except it additionally takes an encoding.
Definition: ctype.h:180
int rb_enc_toupper(int c, rb_encoding *enc)
Identical to rb_toupper(), except it additionally takes an encoding.
Definition: encoding.c:1236
static bool rb_enc_isdigit(OnigCodePoint c, rb_encoding *enc)
Identical to rb_isdigit(), except it additionally takes an encoding.
Definition: ctype.h:208
VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
Identical to rb_enc_sprintf(), except it takes a va_list instead of variadic arguments.
Definition: sprintf.c:1179
VALUE rb_enc_sprintf(rb_encoding *enc, const char *fmt,...)
Identical to rb_sprintf(), except it additionally takes an encoding.
Definition: sprintf.c:1198
#define TYPE(_)
Old name of rb_type.
Definition: value_type.h:108
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition: value_type.h:87
#define ENC_CODERANGE_7BIT
Old name of RUBY_ENC_CODERANGE_7BIT.
Definition: coderange.h:180
#define ENC_CODERANGE_VALID
Old name of RUBY_ENC_CODERANGE_VALID.
Definition: coderange.h:181
#define RFLOAT_VALUE
Old name of rb_float_value.
Definition: double.h:28
#define T_STRING
Old name of RUBY_T_STRING.
Definition: value_type.h:78
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition: long.h:48
#define T_FLOAT
Old name of RUBY_T_FLOAT.
Definition: value_type.h:64
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition: value_type.h:57
#define ECONV_UNDEF_REPLACE
Old name of RUBY_ECONV_UNDEF_REPLACE.
Definition: transcode.h:526
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition: value_type.h:63
#define ENC_CODERANGE(obj)
Old name of RB_ENC_CODERANGE.
Definition: coderange.h:184
#define ENC_CODERANGE_UNKNOWN
Old name of RUBY_ENC_CODERANGE_UNKNOWN.
Definition: coderange.h:179
#define FIXABLE
Old name of RB_FIXABLE.
Definition: fixnum.h:25
#define LONG2FIX
Old name of RB_INT2FIX.
Definition: long.h:49
#define ECONV_INVALID_REPLACE
Old name of RUBY_ECONV_INVALID_REPLACE.
Definition: transcode.h:524
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition: value_type.h:76
#define T_HASH
Old name of RUBY_T_HASH.
Definition: value_type.h:65
#define NUM2INT
Old name of RB_NUM2INT.
Definition: int.h:44
#define Qnil
Old name of RUBY_Qnil.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition: long.h:46
#define NIL_P
Old name of RB_NIL_P.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define ENC_CODERANGE_SET(obj, cr)
Old name of RB_ENC_CODERANGE_SET.
Definition: coderange.h:186
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition: value_type.h:88
#define ruby_debug
This variable controls whether the interpreter is in debug mode.
Definition: error.h:482
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3627
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
Definition: error.h:471
VALUE rb_eRuntimeError
RuntimeError exception.
Definition: error.c:1401
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition: error.c:465
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1404
void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt,...)
Identical to rb_raise(), except it additionally takes an encoding.
Definition: error.c:3608
VALUE rb_Float(VALUE val)
This is the logic behind Kernel#Float.
Definition: object.c:3593
VALUE rb_Integer(VALUE val)
This is the logic behind Kernel#Integer.
Definition: object.c:3261
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition: object.c:678
Encoding relates APIs.
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Identical to rb_enc_associate_index(), except it takes an encoding itself instead of its index.
Definition: encoding.c:1007
int rb_enc_codelen(int code, rb_encoding *enc)
Queries the number of bytes requested to represent the passed code point using the passed encoding.
Definition: encoding.c:1226
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
Look for the "common" encoding between the two.
Definition: encoding.c:1125
int rb_enc_to_index(rb_encoding *enc)
Queries the index of the encoding.
Definition: encoding.c:191
static char * rb_enc_right_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the right boundary of a character.
Definition: encoding.h:704
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
Identical to rb_enc_compatible(), except it raises an exception instead of returning NULL.
Definition: encoding.c:1047
static int rb_enc_mbcput(unsigned int c, void *buf, rb_encoding *enc)
Identical to rb_enc_uint_chr(), except it writes back to the passed buffer instead of allocating one.
Definition: encoding.h:643
rb_encoding * rb_enc_from_index(int idx)
Identical to rb_find_encoding(), except it takes an encoding index instead of a Ruby object.
Definition: encoding.c:402
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Queries the number of bytes of the character at the passed pointer.
Definition: encoding.c:1164
VALUE rb_enc_associate_index(VALUE obj, int encindex)
Identical to rb_enc_set_index(), except it additionally does contents fix-up depending on the passed ...
Definition: encoding.c:979
rb_encoding * rb_enc_get(VALUE obj)
Identical to rb_enc_get_index(), except the return type.
Definition: encoding.c:1013
static const char * rb_enc_name(rb_encoding *enc)
Queries the (canonical) name of the passed encoding.
Definition: encoding.h:417
static int rb_enc_mbminlen(rb_encoding *enc)
Queries the minimum number of bytes that the passed encoding needs to represent a character.
Definition: encoding.h:432
char * rb_enc_nth(const char *head, const char *tail, long nth, rb_encoding *enc)
Queries the n-th character.
Definition: string.c:2921
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
Identical to rb_str_conv_enc(), except it additionally takes IO encoder options.
Definition: string.c:1154
long rb_enc_strlen(const char *head, const char *tail, rb_encoding *enc)
Counts the number of characters of the passed string, according to the passed encoding.
Definition: string.c:2251
long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr)
Scans the passed string until it finds something odd.
Definition: string.c:764
VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
Identical to rb_check_id_cstr(), except for the return type.
Definition: symbol.c:1226
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Exports an integer into a buffer.
Definition: bignum.c:3588
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
Identical to rb_cstr2inum(), except it takes Ruby's strings instead of C's.
Definition: bignum.c:4308
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
Calculates the number of words needed represent the absolute value of the passed integer.
Definition: bignum.c:3424
int rb_absint_singlebit_p(VALUE val)
Tests abs(val) consists only of a bit or not.
Definition: bignum.c:3487
VALUE rb_big2str(VALUE x, int base)
Generates a place-value representation of the passed integer.
Definition: bignum.c:5127
#define INTEGER_PACK_BIG_ENDIAN
Big endian combination.
Definition: bignum.h:572
VALUE rb_dbl2big(double d)
Converts a C's double into a bignum.
Definition: bignum.c:5285
#define INTEGER_PACK_2COMP
Uses 2's complement representation.
Definition: bignum.h:549
VALUE rb_check_hash_type(VALUE obj)
Try converting an object to its hash representation using its to_hash method, if any.
Definition: hash.c:1864
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Identical to rb_hash_lookup(), except you can specify what to return on misshits.
Definition: hash.c:2086
VALUE rb_int_positive_pow(long x, unsigned long y)
Raises the passed x to the power of y.
Definition: numeric.c:4559
VALUE rb_rational_num(VALUE rat)
Queries the numerator of the passed Rational.
Definition: rational.c:1990
VALUE rb_rational_den(VALUE rat)
Queries the denominator of the passed Rational.
Definition: rational.c:1996
size_t rb_str_capacity(VALUE str)
Queries the capacity of the given string.
Definition: string.c:934
void rb_str_modify(VALUE str)
Declares that the string is about to be modified.
Definition: string.c:2642
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition: string.c:3254
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
Definition: string.c:2694
VALUE rb_str_new(const char *ptr, long len)
Allocates an instance of rb_cString.
Definition: string.c:1020
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition: string.c:2845
VALUE rb_str_resize(VALUE str, long len)
Overwrites the length of the string.
Definition: string.c:3302
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
Definition: string.c:1627
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
Definition: string.c:1770
VALUE rb_sym2str(VALUE id)
Identical to rb_id2str(), except it takes an instance of rb_cSymbol rather than an ID.
Definition: symbol.c:970
int len
Length of the buffer.
Definition: io.h:8
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Formats a string.
Definition: sprintf.c:214
VALUE rb_f_sprintf(int argc, const VALUE *argv)
Identical to rb_str_format(), except how the arguments are arranged.
Definition: sprintf.c:208
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
Definition: sprintf.c:1217
VALUE rb_str_vcatf(VALUE dst, const char *fmt, va_list ap)
Identical to rb_str_catf(), except it takes a va_list.
Definition: sprintf.c:1230
VALUE rb_vsprintf(const char *fmt, va_list ap)
Identical to rb_sprintf(), except it takes a va_list.
Definition: sprintf.c:1211
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
Definition: sprintf.c:1240
#define rb_long2int
Just another name of rb_long2int_inline.
Definition: long.h:62
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition: memory.h:367
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition: memory.h:162
#define RBASIC(obj)
Convenient casting macro.
Definition: rbasic.h:40
#define StringValue(v)
Ensures that the parameter object is a String.
Definition: rstring.h:66
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
Definition: rstring.h:442
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
Definition: rstring.h:416
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
Definition: rstring.h:488
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
Definition: rstring.h:367
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
Definition: rstring.h:89
int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap)
Identical to ruby_snprintf(), except it takes a va_list.
Definition: sprintf.c:1014
int ruby_snprintf(char *str, size_t n, char const *fmt,...)
Our own locale-insensitive version of snprintf(3).
Definition: sprintf.c:1041
#define RTEST
This is an old name of RB_TEST.
Defines old _.
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition: value.h:63
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition: value_type.h:376