summaryrefslogtreecommitdiff
path: root/sprintf.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-05-24 14:36:54 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-05-24 14:36:54 +0000
commitce8e2d54049ddbe4947ed90295b1b4d11ebaaa52 (patch)
treeb06c84e6da75e1a9821f6decc192299e5be8101c /sprintf.c
parent60e8cd2e686efd3a965cb43ae5963ce31fc90d71 (diff)
Feature #5896
* vsnprintf.c (BSD_vfprintf): [EXPERIMENTAL] object representation in rb_enc_vsprintf(). [Feature #5896] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35776 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'sprintf.c')
-rw-r--r--sprintf.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/sprintf.c b/sprintf.c
index 5927c25..d705566 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -1146,6 +1146,11 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
#define BSD__hdtoa ruby_hdtoa
#include "vsnprintf.c"
+typedef struct {
+ rb_printf_buffer base;
+ volatile VALUE value;
+} rb_printf_buffer_extra;
+
static int
ruby__sfvwrite(register rb_printf_buffer *fp, register struct __suio *uio)
{
@@ -1172,10 +1177,41 @@ ruby__sfvwrite(register rb_printf_buffer *fp, register struct __suio *uio)
return 0;
}
+static char *
+ruby__sfvextra(rb_printf_buffer *fp, size_t valsize, void *valp, long *sz)
+{
+ VALUE value, result = (VALUE)fp->_bf._base;
+ rb_encoding *enc;
+ char *cp;
+
+ if (valsize != sizeof(VALUE)) return 0;
+ value = *(VALUE *)valp;
+ if (RBASIC(result)->klass) {
+ rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
+ }
+ value = rb_obj_as_string(value);
+ enc = rb_enc_compatible(result, value);
+ if (enc) {
+ rb_enc_associate(result, enc);
+ }
+ else {
+ enc = rb_enc_get(result);
+ value = rb_str_conv_enc_opts(value, rb_enc_get(value), enc,
+ ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE,
+ Qnil);
+ *(volatile VALUE *)valp = value;
+ }
+ StringValueCStr(value);
+ RSTRING_GETMEM(value, cp, *sz);
+ ((rb_printf_buffer_extra *)fp)->value = value;
+ return cp;
+}
+
VALUE
rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
{
- rb_printf_buffer f;
+ rb_printf_buffer_extra buffer;
+#define f buffer.base
VALUE result;
f._flags = __SWR | __SSTR;
@@ -1194,9 +1230,12 @@ rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
f._p = (unsigned char *)RSTRING_PTR(result);
RBASIC(result)->klass = 0;
f.vwrite = ruby__sfvwrite;
+ f.vextra = ruby__sfvextra;
+ buffer.value = 0;
BSD_vfprintf(&f, fmt, ap);
RBASIC(result)->klass = rb_cString;
rb_str_resize(result, (char *)f._p - RSTRING_PTR(result));
+#undef f
return result;
}
@@ -1236,7 +1275,8 @@ rb_sprintf(const char *format, ...)
VALUE
rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
{
- rb_printf_buffer f;
+ rb_printf_buffer_extra buffer;
+#define f buffer.base
VALUE klass;
StringValue(str);
@@ -1249,9 +1289,12 @@ rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
klass = RBASIC(str)->klass;
RBASIC(str)->klass = 0;
f.vwrite = ruby__sfvwrite;
+ f.vextra = ruby__sfvextra;
+ buffer.value = 0;
BSD_vfprintf(&f, fmt, ap);
RBASIC(str)->klass = klass;
rb_str_resize(str, (char *)f._p - RSTRING_PTR(str));
+#undef f
return str;
}