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
*/
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
pad_char = ' ';
prefix_char = NUL;
s_to_free = NULL;
+ free_zcopy = 0;
s_unicode = 0;
fmt++;
* 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:
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);
*/
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
u_wide_int ui_num;
char num_buf[NUM_BUF_SIZE];
- char char_buf[2]; /* for printing %% and %<unknown> */
+ char char_buf[2]; /* for printing %% and %<unknown> */
zend_bool free_s; /* free string if allocated here */
#ifdef HAVE_LOCALE_H
pad_char = ' ';
prefix_char = NUL;
free_s = 0;
+ free_zcopy = 0;
s_unicode = 0;
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:
* 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);