sprintf.c: NULL as str
* sprintf.c (ruby_vsnprintf, ruby_snprintf): allow NULL as str, just count the expected buffer size. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59789 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
6c3c48e3d5
commit
067d9e9ce9
@ -90,6 +90,13 @@ printf_test_call(int argc, VALUE *argv, VALUE self)
|
|||||||
return rb_assoc_new(result, rb_usascii_str_new_cstr(format));
|
return rb_assoc_new(result, rb_usascii_str_new_cstr(format));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
snprintf_count(VALUE self, VALUE str)
|
||||||
|
{
|
||||||
|
int n = ruby_snprintf(NULL, 0, "%s", StringValueCStr(str));
|
||||||
|
return INT2FIX(n);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Init_printf(void)
|
Init_printf(void)
|
||||||
{
|
{
|
||||||
@ -98,4 +105,5 @@ Init_printf(void)
|
|||||||
rb_define_singleton_method(m, "v", printf_test_v, 1);
|
rb_define_singleton_method(m, "v", printf_test_v, 1);
|
||||||
rb_define_singleton_method(m, "q", printf_test_q, 1);
|
rb_define_singleton_method(m, "q", printf_test_q, 1);
|
||||||
rb_define_singleton_method(m, "call", printf_test_call, -1);
|
rb_define_singleton_method(m, "call", printf_test_call, -1);
|
||||||
|
rb_define_singleton_method(m, "sncount", snprintf_count, 1);
|
||||||
}
|
}
|
||||||
|
20
sprintf.c
20
sprintf.c
@ -1261,21 +1261,29 @@ ruby_ultoa(unsigned long val, char *endp, int base, int flags)
|
|||||||
return BSD__ultoa(val, endp, base, octzero, xdigs);
|
return BSD__ultoa(val, endp, base, octzero, xdigs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
|
||||||
|
|
||||||
int
|
int
|
||||||
ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
if (str && (ssize_t)n < 1)
|
||||||
|
return (EOF);
|
||||||
|
return ruby_do_vsnprintf(str, n, fmt, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
rb_printf_buffer f;
|
rb_printf_buffer f;
|
||||||
|
|
||||||
if ((int)n < 1)
|
|
||||||
return (EOF);
|
|
||||||
f._flags = __SWR | __SSTR;
|
f._flags = __SWR | __SSTR;
|
||||||
f._bf._base = f._p = (unsigned char *)str;
|
f._bf._base = f._p = (unsigned char *)str;
|
||||||
f._bf._size = f._w = n - 1;
|
f._bf._size = f._w = str ? (n - 1) : 0;
|
||||||
f.vwrite = BSD__sfvwrite;
|
f.vwrite = BSD__sfvwrite;
|
||||||
f.vextra = 0;
|
f.vextra = 0;
|
||||||
ret = (int)BSD_vfprintf(&f, fmt, ap);
|
ret = (int)BSD_vfprintf(&f, fmt, ap);
|
||||||
*f._p = 0;
|
if (str) *f._p = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1285,11 +1293,11 @@ ruby_snprintf(char *str, size_t n, char const *fmt, ...)
|
|||||||
int ret;
|
int ret;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if ((int)n < 1)
|
if (str && (ssize_t)n < 1)
|
||||||
return (EOF);
|
return (EOF);
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
ret = ruby_vsnprintf(str, n, fmt, ap);
|
ret = ruby_do_vsnprintf(str, n, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -184,4 +184,8 @@ class Test_SPrintf < Test::Unit::TestCase
|
|||||||
assert_equal(" a", Bug::Printf.("s", "a", width: 3, prec: 3)[0])
|
assert_equal(" a", Bug::Printf.("s", "a", width: 3, prec: 3)[0])
|
||||||
assert_equal("a ", Bug::Printf.("s", "a", minus: true, width: 3, prec: 3)[0])
|
assert_equal("a ", Bug::Printf.("s", "a", minus: true, width: 3, prec: 3)[0])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_snprintf_count
|
||||||
|
assert_equal(3, Bug::Printf.sncount("foo"))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user