From: Marcus Boerger Date: Thu, 7 Feb 2008 18:40:29 +0000 (+0000) Subject: - Add %Z to *printf X-Git-Tag: RELEASE_2_0_0a1~579 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=602dd615e9580a181a288cd32d78e93a93b6df6c;p=php - Add %Z to *printf --- diff --git a/README.UNICODE-UPGRADES b/README.UNICODE-UPGRADES index dac7f8b2af..a7c7f8dc8b 100644 --- a/README.UNICODE-UPGRADES +++ b/README.UNICODE-UPGRADES @@ -540,6 +540,19 @@ Unicode strings: zend_error(E_WARNING, "%v::__toString() did not return anything", Z_OBJCE_P(object)->name); + %Z + This format prints a zval's value. You can specify the minimum length + of the string representation using "%*Z" as well as the absolute length + using "%.*Z". The following example is taken from the engine and + therefor uses zend_spprintf rather than spprintf. Further more clen is + an integer that is smaller than Z_UNILEN_P(callable). + + zend_spprintf(error, 0, "class '%.*Z' not found", clen, callable); + + The function allows to output any kind of zaval values, as long as a + string (or unicode) conversion is available. Note that printing non + string zvals outside of request time is not possible. + Since [v]spprintf() can only output native strings there are also the new functions [v]uspprintf() and [v]zspprintf() that create unicode strings and return the number of characters printed. That is they return the length rather diff --git a/main/snprintf.c b/main/snprintf.c index 91e0b67cd4..3890871c1d 100644 --- a/main/snprintf.c +++ b/main/snprintf.c @@ -573,17 +573,18 @@ typedef struct buf_area buffy; */ static int format_converter(register buffy * odp, const char *fmt, va_list ap) /* {{{ */ { - register char *sp; - register char *bep; - register int cc = 0; - register int i; + char *sp; + char *bep; + int cc = 0; + int i; - register char *s = NULL; - register UChar *u = NULL; + char *s = NULL; + UChar *u = NULL; char *q; - int s_len, s_unicode, u_len; + int s_len, s_unicode, u_len, free_zcopy; + zval *zvp, zcopy; - register int min_width = 0; + int min_width = 0; int precision = 0; enum { LEFT, RIGHT @@ -631,6 +632,7 @@ static int format_converter(register buffy * odp, const char *fmt, va_list ap) / pad_char = ' '; prefix_char = NUL; s_to_free = NULL; + free_zcopy = 0; s_unicode = 0; fmt++; @@ -778,6 +780,18 @@ static int format_converter(register buffy * odp, const char *fmt, va_list ap) / * It is reset to ' ' by non-numeric formats */ switch (*fmt) { + case 'Z': + zvp = (zval*) va_arg(ap, zval*); + zend_make_string_zval(zvp, &zcopy, &free_zcopy); + if (free_zcopy) { + zvp = &zcopy; + } + s_len = Z_UNILEN_P(zvp); + s = Z_STRVAL_P(zvp); + if (adjust_precision && precision < s_len) { + s_len = precision; + } + break; case 'u': switch(modifier) { default: @@ -1203,7 +1217,12 @@ fmt_error: s++; } - if (s_to_free) efree(s_to_free); + if (s_to_free) { + efree(s_to_free); + } + if (free_zcopy) { + zval_dtor(&zcopy); + } if (adjust_width && adjust == LEFT && min_width > s_len) PAD(min_width, s_len, pad_char); diff --git a/main/spprintf.c b/main/spprintf.c index 219a767322..90f3c380fb 100644 --- a/main/spprintf.c +++ b/main/spprintf.c @@ -214,12 +214,12 @@ do { \ */ static void xbuf_format_converter(int unicode, smart_str *xbuf, const char *fmt, va_list ap) /* {{{ */ { - register char *s = NULL; - register UChar *u = NULL; + char *s = NULL; + UChar *u = NULL; char *q; - int s_len, s_unicode, u_len; - - register int min_width = 0; + int s_len, s_unicode, u_len, free_zcopy; + zval *zvp, zcopy; + int min_width = 0; int precision = 0; enum { LEFT, RIGHT @@ -232,7 +232,7 @@ static void xbuf_format_converter(int unicode, smart_str *xbuf, const char *fmt, u_wide_int ui_num; char num_buf[NUM_BUF_SIZE]; - char char_buf[2]; /* for printing %% and % */ + char char_buf[2]; /* for printing %% and % */ zend_bool free_s; /* free string if allocated here */ #ifdef HAVE_LOCALE_H @@ -264,6 +264,7 @@ static void xbuf_format_converter(int unicode, smart_str *xbuf, const char *fmt, pad_char = ' '; prefix_char = NUL; free_s = 0; + free_zcopy = 0; s_unicode = 0; fmt++; @@ -411,6 +412,23 @@ static void xbuf_format_converter(int unicode, smart_str *xbuf, const char *fmt, * It is reset to ' ' by non-numeric formats */ switch (*fmt) { + case 'Z': + zvp = (zval*) va_arg(ap, zval*); + if (unicode) { + zend_make_unicode_zval(zvp, &zcopy, &free_zcopy); + s_unicode = 1; + } else { + zend_make_string_zval(zvp, &zcopy, &free_zcopy); + } + if (free_zcopy) { + zvp = &zcopy; + } + s_len = Z_UNILEN_P(zvp); + s = Z_STRVAL_P(zvp); + if (adjust_precision && precision < s_len) { + s_len = precision; + } + break; case 'u': switch(modifier) { default: @@ -838,7 +856,12 @@ fmt_error: * Print the string s. */ INS_STRING(unicode, s_unicode, xbuf, s, s_len); - if (free_s) efree(s); + if (free_s) { + efree(s); + } + if (free_zcopy) { + zval_dtor(&zcopy); + } if (adjust_width && adjust == LEFT && min_width > s_len) { PAD(unicode, xbuf, min_width - s_len, pad_char);