andrei Tue Dec 19 18:41:40 2006 UTC Modified files: /php-src/ext/standard formatted_print.c Log: Unicode support in *printf() functions. (Antony, Andrei)
http://cvs.php.net/viewvc.cgi/php-src/ext/standard/formatted_print.c?r1=1.91&r2=1.92&diff_format=u Index: php-src/ext/standard/formatted_print.c diff -u php-src/ext/standard/formatted_print.c:1.91 php-src/ext/standard/formatted_print.c:1.92 --- php-src/ext/standard/formatted_print.c:1.91 Tue Dec 19 13:13:48 2006 +++ php-src/ext/standard/formatted_print.c Tue Dec 19 18:41:40 2006 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: formatted_print.c,v 1.91 2006/12/19 13:13:48 dmitry Exp $ */ +/* $Id: formatted_print.c,v 1.92 2006/12/19 18:41:40 andrei Exp $ */ #include <math.h> /* modf() */ #include "php.h" @@ -43,6 +43,9 @@ #define MAX_FLOAT_DIGITS 38 #define MAX_FLOAT_PRECISION 40 +#define PHP_OUTPUT 0 +#define PHP_RUNTIME 1 + #if 0 /* trick to control varargs functions through cpp */ # define PRINTF_DEBUG(arg) php_printf arg @@ -53,7 +56,10 @@ static char hexchars[] = "0123456789abcdef"; static char HEXCHARS[] = "0123456789ABCDEF"; +static UChar u_hexchars[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66}; +static UChar u_HEXCHARS[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}; +/* php_sprintf_appendchar() {{{ */ inline static void php_sprintf_appendchar(char **buffer, int *pos, int *size, char add TSRMLS_DC) { @@ -65,8 +71,21 @@ PRINTF_DEBUG(("sprintf: appending '%c', pos=\n", add, *pos)); (*buffer)[(*pos)++] = add; } +/* }}} */ +/* php_u_sprintf_appendchar() {{{ */ +inline static void +php_u_sprintf_appendchar(UChar **buffer, int *pos, int *size, UChar add TSRMLS_DC) +{ + if ((*pos + 1) >= *size) { + *size <<= 1; + *buffer = eurealloc(*buffer, *size); + } + (*buffer)[(*pos)++] = add; +} +/* }}} */ +/* php_sprintf_appendstring() {{{ */ inline static void php_sprintf_appendstring(char **buffer, int *pos, int *size, char *add, int min_width, int max_width, char padding, @@ -115,10 +134,57 @@ } } } +/* }}} */ + +/* php_u_sprintf_appendstring() {{{ */ +inline static void +php_u_sprintf_appendstring(UChar **buffer, int *pos, int *size, UChar *add, + int min_width, int max_width, UChar padding, + int alignment, int len, int neg, int expprec, int always_sign) +{ + register int npad; + int req_size; + int copy_len; + + copy_len = (expprec ? MIN(max_width, len) : len); + npad = min_width - copy_len; + if (npad < 0) { + npad = 0; + } + + req_size = *pos + MAX(min_width, copy_len) + 1; + + if (req_size > *size) { + while (req_size > *size) { + *size <<= 1; + } + *buffer = eurealloc(*buffer, *size); + } + if (alignment == ALIGN_RIGHT) { + if ((neg || always_sign) && padding == 0x30 /* '0' */) { + (*buffer)[(*pos)++] = (neg) ? 0x2D /* '-' */ : 0x2B /* '+' */; + add++; + len--; + copy_len--; + } + while (npad-- > 0) { + (*buffer)[(*pos)++] = padding; + } + } + u_memcpy(&(*buffer)[*pos], add, copy_len + 1); + *pos += copy_len; + if (alignment == ALIGN_LEFT) { + while (npad--) { + (*buffer)[(*pos)++] = padding; + } + } +} +/* }}} */ +/* php_sprintf_appendint() {{{ */ inline static void -php_sprintf_appendint(char **buffer, int *pos, int *size, long number, +php_sprintf_appendint(char **buffer, int *pos, int *size, long number, int width, char padding, int alignment, int always_sign) { @@ -158,7 +224,49 @@ padding, alignment, (NUM_BUF_SIZE - 1) - i, neg, 0, always_sign); } +/* }}} */ +/* php_u_sprintf_appendint() {{{ */ +inline static void +php_u_sprintf_appendint(UChar **buffer, int *pos, int *size, long number, + int width, UChar padding, int alignment, + int always_sign) +{ + UChar numbuf[NUM_BUF_SIZE]; + register unsigned long magn, nmagn; + register unsigned int i = NUM_BUF_SIZE - 1, neg = 0; + + if (number < 0) { + neg = 1; + magn = ((unsigned long) -(number + 1)) + 1; + } else { + magn = (unsigned long) number; + } + + /* Can't right-pad 0's on integers */ + if (alignment==0 && padding== 0x30 /* '0' */) padding = 0x20 /* ' ' */; + + numbuf[i] = 0x0A /* '\0' */; + + do { + nmagn = magn / 10; + + numbuf[--i] = (UChar)(magn - (nmagn * 10)) + 0x30 /* '0' */; + magn = nmagn; + } + while (magn > 0 && i > 0); + if (neg) { + numbuf[--i] = 0x2D /* '-' */; + } else if (always_sign) { + numbuf[--i] = 0x2B /* '+' */; + } + php_u_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0, + padding, alignment, (NUM_BUF_SIZE - 1) - i, + neg, 0, always_sign); +} +/* }}} */ + +/* php_sprintf_appenduint() {{{ */ inline static void php_sprintf_appenduint(char **buffer, int *pos, int *size, unsigned long number, @@ -188,7 +296,38 @@ php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0, padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, 0, 0); } +/* }}} */ +/* php_u_sprintf_appenduint() {{{ */ +inline static void +php_u_sprintf_appenduint(UChar **buffer, int *pos, int *size, + unsigned long number, + int width, UChar padding, int alignment) +{ + UChar numbuf[NUM_BUF_SIZE]; + register unsigned long magn, nmagn; + register unsigned int i = NUM_BUF_SIZE - 1; + + magn = (unsigned int) number; + + /* Can't right-pad 0's on integers */ + if (alignment == 0 && padding == 0x30 /* '0' */) padding = 0x20 /* ' ' */; + + numbuf[i] = 0x0A /* '\0' */; + + do { + nmagn = magn / 10; + + numbuf[--i] = (UChar)(magn - (nmagn * 10)) + 0x30 /* '0' */; + magn = nmagn; + } while (magn > 0 && i > 0); + + php_u_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0, + padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, 0, 0); +} +/* }}} */ + +/* php_sprintf_appenddouble() {{{ */ inline static void php_sprintf_appenddouble(char **buffer, int *pos, int *size, double number, @@ -238,9 +377,9 @@ #ifdef HAVE_LOCALE_H lconv = localeconv(); #endif - s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision, - (fmt == 'f')?LCONV_DECIMAL_POINT:'.', - &is_negative, &num_buf[1], &s_len); + s = php_conv_fp((fmt == 'f')?'F':fmt, number, NO, precision, + (fmt == 'f')?LCONV_DECIMAL_POINT:'.', + &is_negative, &num_buf[1], &s_len); if (is_negative) { num_buf[0] = '-'; s = num_buf; @@ -279,8 +418,133 @@ php_sprintf_appendstring(buffer, pos, size, s, width, 0, padding, alignment, s_len, is_negative, 0, always_sign); } +/* }}} */ + +/* php_u_sprintf_appenddouble() {{{ */ +inline static void +php_u_sprintf_appenddouble(UChar **buffer, int *pos, + int *size, double number, + int width, UChar padding, + int alignment, int precision, + int adjust, UChar fmt, + int always_sign + TSRMLS_DC) +{ + char num_buf[NUM_BUF_SIZE]; + char *s = NULL, *q, s_fmt; + UChar *uni_s; + int s_len = 0, is_negative = 0; +#ifdef HAVE_LOCALE_H + struct lconv *lconv; +#endif + + if ((adjust & ADJ_PRECISION) == 0) { + precision = FLOAT_PRECISION; + } else if (precision > MAX_FLOAT_PRECISION) { + precision = MAX_FLOAT_PRECISION; + } + + if (zend_isnan(number)) { + UChar *nan = USTR_MAKE("NaN"); + is_negative = (number<0); + php_u_sprintf_appendstring(buffer, pos, size, nan, 3, 0, padding, + alignment, precision, is_negative, 0, always_sign); + efree(nan); + return; + } + + if (zend_isinf(number)) { + UChar *inf = USTR_MAKE("INF"); + is_negative = (number<0); + php_u_sprintf_appendstring(buffer, pos, size, inf, 3, 0, padding, + alignment, precision, is_negative, 0, always_sign); + efree(inf); + return; + } + + switch (fmt) { + case 0x66 /* 'f' */: + s_fmt = 'f'; + break; + case 0x46 /* 'F' */: + s_fmt = 'F'; + break; + case 0x65 /* 'e' */: + s_fmt = 'e'; + break; + case 0x45 /* 'E' */: + s_fmt = 'E'; + break; + case 0x67 /* 'g' */: + s_fmt = 'g'; + break; + case 0x47 /* 'G' */: + s_fmt = 'G'; + break; + } + + switch (fmt) { + case 0x65 /* 'e' */: + if (precision) { + precision--; + } + case 0x45 /* 'E' */: + case 0x46 /* 'F' */: + case 0x66 /* 'f' */: +#ifdef HAVE_LOCALE_H + lconv = localeconv(); +#endif + s = php_conv_fp((s_fmt == 'f')?'F':s_fmt, number, NO, precision, + (s_fmt == 'f')?LCONV_DECIMAL_POINT:'.', + &is_negative, &num_buf[1], &s_len); + if (is_negative) { + num_buf[0] = '-'; + s = num_buf; + s_len++; + } else if (always_sign) { + num_buf[0] = '+'; + s = num_buf; + s_len++; + } + s[s_len] = '\0'; + break; + + case 0x67 /* 'g' */: + case 0x47 /* 'G' */: + if (precision == 0) + precision = 1; + /* + * * We use &num_buf[ 1 ], so that we have room for the sign + */ +#ifdef HAVE_LOCALE_H + lconv = localeconv(); +#endif + s = php_gcvt(number, precision, LCONV_DECIMAL_POINT, (s_fmt == 'G')?'E':'e', &num_buf[1]); + is_negative = 0; + if (*s == '-') { + is_negative = 1; + s = &num_buf[1]; + } else if (always_sign) { + num_buf[0] = '+'; + s = num_buf; + } + s_len = strlen(s); + if (fmt == 0x47 /* 'G' */ && (q = strchr(s, 'e')) != NULL) { + *q = 'E'; + } + break; + } + + uni_s = zend_ascii_to_unicode(s, s_len + 1 ZEND_FILE_LINE_CC); + php_u_sprintf_appendstring(buffer, pos, size, uni_s, width, 0, padding, + alignment, s_len, is_negative, 0, always_sign); + efree(uni_s); +} +/* }}} */ + +/* php_sprintf_append2n() {{{ */ inline static void php_sprintf_append2n(char **buffer, int *pos, int *size, long number, int width, char padding, int alignment, int n, @@ -309,8 +573,35 @@ padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, expprec, 0); } +/* }}} */ + +/* php_u_sprintf_append2n() {{{ */ +inline static void +php_u_sprintf_append2n(UChar **buffer, int *pos, int *size, long number, + int width, UChar padding, int alignment, int n, + UChar *chartable, int expprec) +{ + UChar numbuf[NUM_BUF_SIZE]; + register unsigned long num; + register unsigned int i = NUM_BUF_SIZE - 1; + register int andbits = (1 << n) - 1; + + num = (unsigned long) number; + numbuf[i] = '\0'; + do { + numbuf[--i] = chartable[(num & andbits)]; + num >>= n; + } + while (num > 0); + php_u_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0, + padding, alignment, (NUM_BUF_SIZE - 1) - i, + 0, expprec, 0); +} +/* }}} */ + +/* php_sprintf_getnumber() {{{ */ inline static long php_sprintf_getnumber(char *buffer, int *pos) { @@ -325,8 +616,25 @@ *pos += i; return num; } +/* }}} */ -/* {{{ php_formatted_print +/* php_u_sprintf_getnumber() {{{ */ +inline static long +php_u_sprintf_getnumber(UChar *buffer, int *pos) +{ + UChar *endptr; + register long num = zend_u_strtol(&buffer[*pos], &endptr, 10); + register int i = 0; + + if (endptr != NULL) { + i = (endptr - &buffer[*pos]); + } + *pos += i; + return num; +} +/* }}} */ + +/* {{{ php_formatted_print() * New sprintf implementation for PHP. * * Modifiers: @@ -350,8 +658,7 @@ * "X" integer argument is printed as uppercase hexadecimal * */ -static char * -php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC) +static char * php_formatted_print(int ht, int *len, int use_array, int format_offset, int type TSRMLS_DC) { zval ***args, **z_format; int argc, size = 240, inpos = 0, outpos = 0, temppos; @@ -525,9 +832,26 @@ switch (format[inpos]) { case 's': { zval *var, var_copy; - int use_copy; + int use_copy = 0; - zend_make_printable_zval(tmp, &var_copy, &use_copy); + if (Z_TYPE_P(tmp) != IS_UNICODE) { + zend_make_printable_zval(tmp, &var_copy, &use_copy); + } else { + var_copy = *tmp; + zval_copy_ctor(&var_copy); + INIT_PZVAL(&var_copy); + use_copy = 1; + + switch (type) { + case PHP_OUTPUT: + convert_to_string_with_converter(&var_copy, ZEND_U_CONVERTER(UG(output_encoding_conv))); + break; + case PHP_RUNTIME: + default: + convert_to_string_with_converter(&var_copy, ZEND_U_CONVERTER(UG(runtime_encoding_conv))); + break; + } + } if (use_copy) { var = &var_copy; } else { @@ -566,7 +890,6 @@ case 'E': case 'f': case 'F': - /* XXX not done */ convert_to_double(tmp); php_sprintf_appenddouble(&result, &outpos, &size, Z_DVAL_P(tmp), @@ -637,125 +960,476 @@ } /* }}} */ -/* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]]) +/* php_u_formatted_print() {{{ */ +static zstr php_u_formatted_print(int ht, int *len, int use_array, int format_offset, int type TSRMLS_DC) +{ + zval ***args, **z_format; + int argc, size = 240, inpos = 0, outpos = 0, temppos; + int alignment, width, precision, currarg, adjusting, argnum; + UChar *format, *result, padding; + int always_sign; + zstr result_str; + + argc = ZEND_NUM_ARGS(); + + /* verify the number of args */ + if ((use_array && argc != (2 + format_offset)) + || (!use_array && argc < (1 + format_offset))) { + WRONG_PARAM_COUNT_WITH_RETVAL(NULL_ZSTR); + } + args = (zval ***)safe_emalloc(argc, sizeof(zval *), 0); + + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT_WITH_RETVAL(NULL_ZSTR); + } + + if (use_array) { + int i = 1; + zval ***newargs; + zval **array; + + z_format = args[format_offset]; + array = args[1 + format_offset]; + + SEPARATE_ZVAL(array); + convert_to_array_ex(array); + + argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array)); + newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0); + newargs[0] = z_format; + + for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array)); + zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_PP(array))); + + efree(args); + args = newargs; + format_offset = 0; + } + + convert_to_unicode_ex(args[format_offset]); + format = Z_USTRVAL_PP(args[format_offset]); + result = eumalloc(size); + + currarg = 1; + + while (inpos<Z_USTRLEN_PP(args[format_offset])) { + int expprec = 0, multiuse = 0; + zval *tmp; + + if (format[inpos] != 0x25 /* '%' */) { + php_u_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC); + } else if (format[inpos + 1] == 0x25 /* '%' */) { + php_u_sprintf_appendchar(&result, &outpos, &size, 0x25 /* '%' */ TSRMLS_CC); + inpos += 2; + } else { + /* starting a new format specifier, reset variables */ + alignment = ALIGN_RIGHT; + adjusting = 0; + padding = 0x20 /* ' ' */; + always_sign = 0; + inpos++; /* skip the '%' */ + + if ((format[inpos] < 0x7f) && !u_isalpha(format[inpos])) { + /* first look for argnum */ + temppos = inpos; + while (format[temppos] >= 0x30 /* '0' */ && format[temppos] <= 0x39 /* '9' */) temppos++; + if (format[temppos] == 0x24 /* '$' */) { + argnum = php_u_sprintf_getnumber(format, &inpos); + + if (argnum == 0) { + efree(result); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero is not a valid argument number"); + return NULL_ZSTR; + } + + multiuse = 1; + inpos++; /* skip the '$' */ + } else { + argnum = currarg++; + } + + argnum += format_offset; + + /* after argnum comes modifiers */ + for (;; inpos++) { + if (u_isspace(format[inpos]) || format[inpos] == 0x30 /* '0' */) { + padding = format[inpos]; + } else if (format[inpos] == 0x2D /* '-' */) { + alignment = ALIGN_LEFT; + /* space padding, the default */ + } else if (format[inpos] == 0x2B /* '+' */) { + always_sign = 1; + } else if (format[inpos] == 0x27 /* '\'' */) { + padding = format[++inpos]; + } else { + break; + } + } + + /* after modifiers comes width */ + if (isdigit((int)format[inpos])) { + width = php_u_sprintf_getnumber(format, &inpos); + adjusting |= ADJ_WIDTH; + } else { + width = 0; + } + + /* after width and argnum comes precision */ + if (format[inpos] == 0x2E /* '.' */) { + inpos++; + if (format[inpos] >= 0x30 /* '0' */ && format[inpos] <= 0x39 /* '9' */) { + precision = php_u_sprintf_getnumber(format, &inpos); + adjusting |= ADJ_PRECISION; + expprec = 1; + } else { + precision = 0; + } + } else { + precision = 0; + } + } else { + width = precision = 0; + argnum = currarg++ + format_offset; + } + + if (argnum >= argc) { + efree(result); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments"); + return NULL_ZSTR; + } + + if (format[inpos] == 0x6C /* 'l' */) { + inpos++; + } + /* now we expect to find a type specifier */ + if (multiuse) { + MAKE_STD_ZVAL(tmp); + *tmp = **(args[argnum]); + INIT_PZVAL(tmp); + zval_copy_ctor(tmp); + } else { + SEPARATE_ZVAL(args[argnum]); + tmp = *(args[argnum]); + } + + switch (format[inpos]) { + case 0x73 /* 's' */: { + zval *var, var_copy; + int use_copy; + + zend_make_unicode_zval(tmp, &var_copy, &use_copy); + if (use_copy) { + var = &var_copy; + } else { + var = tmp; + } + php_u_sprintf_appendstring(&result, &outpos, &size, + Z_USTRVAL_P(var), + width, precision, padding, + alignment, + Z_USTRLEN_P(var), + 0, expprec, 0); + if (use_copy) { + zval_dtor(&var_copy); + } + break; + } + + case 0x64 /* 'd' */: + convert_to_long(tmp); + php_u_sprintf_appendint(&result, &outpos, &size, + Z_LVAL_P(tmp), + width, padding, alignment, + always_sign); + break; + + case 0x75 /* 'u' */: + convert_to_long(tmp); + php_u_sprintf_appenduint(&result, &outpos, &size, + Z_LVAL_P(tmp), + width, padding, alignment); + break; + + case 0x67 /* 'g' */: + case 0x47 /* 'G' */: + case 0x65 /* 'e' */: + case 0x45 /* 'E' */: + case 0x66 /* 'f' */: + case 0x46 /* 'F' */: + convert_to_double(tmp); + php_u_sprintf_appenddouble(&result, &outpos, &size, + Z_DVAL_P(tmp), + width, padding, alignment, + precision, adjusting, + format[inpos], always_sign + TSRMLS_CC); + break; + + case 0x63 /* 'c' */: + convert_to_long(tmp); + php_u_sprintf_appendchar(&result, &outpos, &size, + (char) Z_LVAL_P(tmp) TSRMLS_CC); + break; + + case 0x6F /* 'o' */: + convert_to_long(tmp); + php_u_sprintf_append2n(&result, &outpos, &size, + Z_LVAL_P(tmp), + width, padding, alignment, 3, + u_hexchars, expprec); + break; + + case 0x78 /* 'x' */: + convert_to_long(tmp); + php_u_sprintf_append2n(&result, &outpos, &size, + Z_LVAL_P(tmp), + width, padding, alignment, 4, + u_hexchars, expprec); + break; + + case 0x58 /* 'X' */: + convert_to_long(tmp); + php_u_sprintf_append2n(&result, &outpos, &size, + Z_LVAL_P(tmp), + width, padding, alignment, 4, + u_HEXCHARS, expprec); + break; + + case 0x62 /* 'b' */: + convert_to_long(tmp); + php_u_sprintf_append2n(&result, &outpos, &size, + Z_LVAL_P(tmp), + width, padding, alignment, 1, + u_hexchars, expprec); + break; + + case 0x25 /* '%' */: + php_u_sprintf_appendchar(&result, &outpos, &size, 0x25 /* '%' */ TSRMLS_CC); + + break; + default: + break; + } + if (multiuse) { + zval_ptr_dtor(&tmp); + } + inpos++; + } + } + + efree(args); + + /* possibly, we have to make sure we have room for the terminating null? */ + result[outpos] = 0; + *len = outpos; + result_str.u = result; + + switch (type) { + case PHP_OUTPUT: + { + UErrorCode status = U_ZERO_ERROR; + char *s; + int s_len; + + zend_unicode_to_string_ex(ZEND_U_CONVERTER(UG(output_encoding_conv)), &s, &s_len, result, outpos, &status); + if(U_FAILURE(status)) { + efree(s); + efree(result); + return NULL_ZSTR; + } + + efree(result_str.v); + result_str.s = s; + *len = s_len; + break; + } + case PHP_RUNTIME: + default: + /* nothing to be done */ + break; + } + + return result_str; +} +/* }}} */ + +/* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]]) U Return a formatted string */ PHP_FUNCTION(user_sprintf) { - char *result; int len; - - if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) { - RETURN_FALSE; + zstr result; + + if (!UG(unicode)) { + if ((result.s = php_formatted_print(ht, &len, 0, 0, PHP_RUNTIME TSRMLS_CC))==NULL) { + RETURN_FALSE; + } + RETVAL_STRINGL(result.s, len, 0); + } else { + result = php_u_formatted_print(ht, &len, 0, 0, PHP_RUNTIME TSRMLS_CC); + if (result.v == NULL) { + RETURN_FALSE; + } + RETVAL_UNICODEL(result.u, len, 0); } - RETVAL_STRINGL(result, len, 0); } /* }}} */ -/* {{{ proto string vsprintf(string format, array args) +/* {{{ proto string vsprintf(string format, array args) U Return a formatted string */ PHP_FUNCTION(vsprintf) { - char *result; int len; - - if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) { - RETURN_FALSE; + zstr result; + + if (!UG(unicode)) { + if ((result.s = php_formatted_print(ht, &len, 1, 0, PHP_RUNTIME TSRMLS_CC))==NULL) { + RETURN_FALSE; + } + RETVAL_STRINGL(result.s, len, 0); + } else { + result = php_u_formatted_print(ht, &len, 1, 0, PHP_RUNTIME TSRMLS_CC); + if (result.v == NULL) { + RETURN_FALSE; + } + RETVAL_UNICODEL(result.u, len, 0); } - RETVAL_STRINGL(result, len, 0); } /* }}} */ -/* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]]) +/* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]]) U Output a formatted string */ PHP_FUNCTION(user_printf) { - char *result; int len; - - if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) { - RETURN_FALSE; + zstr result; + + if (!UG(unicode)) { + if ((result.s = php_formatted_print(ht, &len, 0, 0, PHP_OUTPUT TSRMLS_CC))==NULL) { + RETURN_FALSE; + } + } else { + result = php_u_formatted_print(ht, &len, 0, 0, PHP_OUTPUT TSRMLS_CC); + if (result.v == NULL) { + RETURN_FALSE; + } } - PHPWRITE(result, len); - efree(result); + + PHPWRITE(result.s, len); + efree(result.v); RETURN_LONG(len); } /* }}} */ -/* {{{ proto int vprintf(string format, array args) +/* {{{ proto int vprintf(string format, array args) U Output a formatted string */ PHP_FUNCTION(vprintf) { - char *result; int len; + zstr result; - if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) { - RETURN_FALSE; + if (!UG(unicode)) { + if ((result.s = php_formatted_print(ht, &len, 1, 0, PHP_OUTPUT TSRMLS_CC))==NULL) { + RETURN_FALSE; + } + } else { + result = php_u_formatted_print(ht, &len, 1, 0, PHP_OUTPUT TSRMLS_CC); + if (result.v == NULL) { + RETURN_FALSE; + } } - PHPWRITE(result, len); - efree(result); + + PHPWRITE(result.s, len); + efree(result.v); RETURN_LONG(len); } /* }}} */ -/* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]]) +/* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]]) U Output a formatted string into a stream */ PHP_FUNCTION(fprintf) { php_stream *stream; - zval **arg1; - char *result; - int len; + zval **arg1, **arg2; + zstr result; + int len, ret; if (ZEND_NUM_ARGS() < 2) { WRONG_PARAM_COUNT; } - if (zend_get_parameters_ex(1, &arg1)==FAILURE) { + if (zend_get_parameters_ex(2, &arg1, &arg2)==FAILURE) { RETURN_FALSE; } php_stream_from_zval(stream, arg1); - if ((result=php_formatted_print(ht, &len, 0, 1 TSRMLS_CC))==NULL) { - RETURN_FALSE; + if (Z_TYPE_PP(arg2) != IS_STRING && Z_TYPE_PP(arg2) != IS_UNICODE) { + convert_to_text_ex(arg2); } - php_stream_write(stream, result, len); - - efree(result); + if (Z_TYPE_PP(arg2) == IS_STRING) { + if ((result.s = php_formatted_print(ht, &len, 0, 1, PHP_RUNTIME TSRMLS_CC))==NULL) { + RETURN_FALSE; + } + ret = php_stream_write(stream, result.s, len); + } else { + result = php_u_formatted_print(ht, &len, 0, 1, PHP_RUNTIME TSRMLS_CC); + if (result.v == NULL) { + RETURN_FALSE; + } + ret = php_stream_write_unicode(stream, result.u, len); + } + + efree(result.v); - RETURN_LONG(len); + RETURN_LONG(ret); } /* }}} */ -/* {{{ proto int vfprintf(resource stream, string format, array args) +/* {{{ proto int vfprintf(resource stream, string format, array args) U Output a formatted string into a stream */ PHP_FUNCTION(vfprintf) { php_stream *stream; - zval **arg1; - char *result; - int len; + zval **arg1, **arg2; + zstr result; + int len, ret; if (ZEND_NUM_ARGS() != 3) { WRONG_PARAM_COUNT; } - if (zend_get_parameters_ex(1, &arg1)==FAILURE) { + if (zend_get_parameters_ex(2, &arg1, &arg2)==FAILURE) { RETURN_FALSE; } php_stream_from_zval(stream, arg1); - if ((result=php_formatted_print(ht, &len, 1, 1 TSRMLS_CC))==NULL) { - RETURN_FALSE; + if (Z_TYPE_PP(arg2) != IS_STRING && Z_TYPE_PP(arg2) != IS_UNICODE) { + convert_to_text_ex(arg2); } - php_stream_write(stream, result, len); + if (Z_TYPE_PP(arg2) == IS_STRING) { + if ((result.s = php_formatted_print(ht, &len, 1, 1, PHP_RUNTIME TSRMLS_CC))==NULL) { + RETURN_FALSE; + } + ret = php_stream_write(stream, result.s, len); + } else { + result = php_u_formatted_print(ht, &len, 1, 1, PHP_RUNTIME TSRMLS_CC); + if (result.v == NULL) { + RETURN_FALSE; + } + ret = php_stream_write_unicode(stream, result.u, len); + } - efree(result); + efree(result.v); - RETURN_LONG(len); + RETURN_LONG(ret); } /* }}} */
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php