Added vstrpprintf strpprintf to avoid duplicate string

(the function name maybe improvement)
This commit is contained in:
Xinchen Hui 2014-05-10 00:21:49 +08:00
parent e2890e3a0f
commit 88c550a799
9 changed files with 82 additions and 47 deletions

View File

@ -55,6 +55,7 @@ ZEND_API void (*zend_unblock_interruptions)(void);
ZEND_API void (*zend_ticks_function)(int ticks TSRMLS_DC);
ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap);
ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);
@ -676,6 +677,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS
zend_ticks_function = utility_functions->ticks_function;
zend_on_timeout = utility_functions->on_timeout;
zend_vspprintf = utility_functions->vspprintf_function;
zend_vstrpprintf = utility_functions->vstrpprintf_function;
zend_getenv = utility_functions->getenv_function;
zend_resolve_path = utility_functions->resolve_path_function;

View File

@ -522,6 +522,7 @@ typedef struct _zend_utility_functions {
void (*on_timeout)(int seconds TSRMLS_DC);
int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
int (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap);
zend_string *(*vstrpprintf_function)(size_t max_len, const char *format, va_list ap);
char *(*getenv_function)(char *name, size_t name_len TSRMLS_DC);
char *(*resolve_path_function)(const char *filename, int filename_len TSRMLS_DC);
} zend_utility_functions;
@ -632,6 +633,7 @@ extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, cons
extern ZEND_API void (*zend_on_timeout)(int seconds TSRMLS_DC);
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
extern zend_string *(*zend_vstrpprintf)(size_t max_len, const char *format, va_list ap);
extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
extern ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC);

View File

@ -313,23 +313,20 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_
array_init(&val);
for (i = 0; i < closure->func.common.num_args; i++) {
char *name, *info;
int name_len, info_len;
zend_string *name;
zval info;
if (arg_info->name) {
name_len = zend_spprintf(&name, 0, "%s$%s",
arg_info->pass_by_reference ? "&" : "",
arg_info->name);
name = zend_strpprintf(0, "%s$%s",
arg_info->pass_by_reference ? "&" : "",
arg_info->name);
} else {
name_len = zend_spprintf(&name, 0, "%s$param%d",
arg_info->pass_by_reference ? "&" : "",
i + 1);
name = zend_strpprintf(0, "%s$param%d",
arg_info->pass_by_reference ? "&" : "",
i + 1);
}
info_len = zend_spprintf(&info, 0, "%s",
i >= required ? "<optional>" : "<required>");
// TODO: avoid reallocation ???
add_assoc_stringl_ex(&val, name, name_len, info, info_len);
efree(info);
efree(name);
ZVAL_STR(&info, zend_strpprintf(0, "%s", i >= required ? "<optional>" : "<required>"));
zend_hash_update(Z_ARRVAL(val), name, &info);
STR_RELEASE(name);
arg_info++;
}
zend_hash_str_update(closure->debug_info, "parameter", sizeof("parameter")-1, &val);

View File

@ -618,7 +618,7 @@ ZEND_METHOD(exception, getPrevious)
previous = zend_read_property(default_exception_ce, getThis(), "previous", sizeof("previous")-1, 1 TSRMLS_CC);
RETURN_ZVAL(previous, 1, 0);
}
} /* }}} */
int zend_spprintf(char **message, int max_len, const char *format, ...) /* {{{ */
{
@ -632,19 +632,30 @@ int zend_spprintf(char **message, int max_len, const char *format, ...) /* {{{ *
}
/* }}} */
zend_string *zend_strpprintf(int max_len, const char *format, ...) /* {{{ */
{
va_list arg;
zend_string *str;
va_start(arg, format);
str = zend_vstrpprintf(max_len, format, arg);
va_end(arg);
return str;
}
/* }}} */
/* {{{ proto string Exception::__toString()
Obtain the string representation of the Exception object */
ZEND_METHOD(exception, __toString)
{
zval message, file, line, trace, *exception;
char *str, *prev_str;
int len = 0;
zend_string *str, *prev_str;
zend_fcall_info fci;
zval fname;
DEFAULT_0_PARAMS;
str = estrndup("", 0);
str = STR_EMPTY_ALLOC();
exception = getThis();
ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1);
@ -677,17 +688,17 @@ ZEND_METHOD(exception, __toString)
}
if (Z_STRLEN(message) > 0) {
len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s%s%s",
Z_OBJCE_P(exception)->name->val, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line),
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
len ? "\n\nNext " : "", prev_str);
str = zend_strpprintf(0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s%s%s",
Z_OBJCE_P(exception)->name->val, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line),
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
prev_str->len ? "\n\nNext " : "", prev_str->val);
} else {
len = zend_spprintf(&str, 0, "exception '%s' in %s:%ld\nStack trace:\n%s%s%s",
Z_OBJCE_P(exception)->name->val, Z_STRVAL(file), Z_LVAL(line),
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
len ? "\n\nNext " : "", prev_str);
str = zend_strpprintf(0, "exception '%s' in %s:%ld\nStack trace:\n%s%s%s",
Z_OBJCE_P(exception)->name->val, Z_STRVAL(file), Z_LVAL(line),
(Z_TYPE(trace) == IS_STRING && Z_STRLEN(trace)) ? Z_STRVAL(trace) : "#0 {main}\n",
prev_str->len ? "\n\nNext " : "", prev_str->val);
}
efree(prev_str);
STR_RELEASE(prev_str);
zval_dtor(&message);
zval_dtor(&file);
zval_dtor(&line);
@ -701,11 +712,9 @@ ZEND_METHOD(exception, __toString)
/* We store the result in the private property string so we can access
* the result in uncaught exception handlers without memleaks. */
zend_update_property_string(default_exception_ce, getThis(), "string", sizeof("string")-1, str TSRMLS_CC);
zend_update_property_str(default_exception_ce, getThis(), "string", sizeof("string")-1, str TSRMLS_CC);
// TODO: avoid reallocation ???
RETVAL_STRINGL(str, len);
efree(str);
RETURN_STR(str);
}
/* }}} */

View File

@ -54,6 +54,7 @@ ZEND_API void zend_exception_error(zend_object *exception, int severity TSRMLS_D
/* do not export, in php it's available thru spprintf directly */
int zend_spprintf(char **message, int max_len, const char *format, ...);
zend_string *zend_strpprintf(int max_len, const char *format, ...);
END_EXTERN_C()

View File

@ -621,15 +621,13 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
break;
}
case IS_DOUBLE: {
char *str;
int len;
zend_string *str;
double dval = Z_DVAL_P(op);
TSRMLS_FETCH();
len = zend_spprintf(&str, 0, "%.*G", (int) EG(precision), dval);
str = zend_strpprintf(0, "%.*G", (int) EG(precision), dval);
/* %G already handles removing trailing zeros from the fractional part, yay */
ZVAL_NEW_STR(op, STR_INIT(str, len, 0));
efree(str);
ZVAL_NEW_STR(op, str);
break;
}
case IS_ARRAY:
@ -910,11 +908,7 @@ try_again:
return STR_INIT(buf, len, 0);
}
case IS_DOUBLE: {
char *str;
int len = zend_spprintf(&str, 0, "%.*G", (int) EG(precision), Z_DVAL_P(op));
zend_string *retval = STR_INIT(str, len, 0);
efree(str);
return retval;
return zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(op));
}
case IS_ARRAY:
zend_error(E_NOTICE, "Array to string conversion");
@ -2529,12 +2523,10 @@ ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC) /
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
{
TSRMLS_FETCH();
char *str;
int len;
zend_string *str;
len = zend_spprintf(&str, 0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
ZVAL_NEW_STR(op, STR_INIT(str, len, 0));
efree(str);
str = zend_strpprintf(0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
ZVAL_NEW_STR(op, str);
}
/* }}} */

View File

@ -2095,6 +2095,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
zuf.on_timeout = php_on_timeout;
zuf.stream_open_function = php_stream_open_for_zend;
zuf.vspprintf_function = vspprintf;
zuf.vstrpprintf_function = vstrpprintf;
zuf.getenv_function = sapi_getenv;
zuf.resolve_path_function = php_resolve_path_for_zend;
zend_startup(&zuf, NULL TSRMLS_CC);

View File

@ -799,7 +799,7 @@ PHPAPI int vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap
xbuf_format_converter(&xbuf, format, ap);
if (max_len && xbuf.s->len > max_len) {
if (max_len && xbuf.s && xbuf.s->len > max_len) {
xbuf.s->len = max_len;
}
smart_str_0(&xbuf);
@ -829,6 +829,33 @@ PHPAPI int spprintf(char **pbuf, size_t max_len, const char *format, ...) /* {{{
}
/* }}} */
PHPAPI zend_string *vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */
{
smart_str xbuf = {0};
xbuf_format_converter(&xbuf, format, ap);
if (max_len && xbuf.s && xbuf.s->len > max_len) {
xbuf.s->len = max_len;
}
smart_str_0(&xbuf);
return xbuf.s;
}
/* }}} */
PHPAPI zend_string *strpprintf(size_t max_len, const char *format, ...) /* {{{ */
{
va_list ap;
zend_string *str;
va_start(ap, format);
str = vstrpprintf(max_len, format, ap);
va_end(ap);
return str;
}
/* }}} */
/*
* Local variables:
* tab-width: 4

View File

@ -40,6 +40,10 @@ BEGIN_EXTERN_C()
PHPAPI int spprintf( char **pbuf, size_t max_len, const char *format, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
PHPAPI int vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) PHP_ATTRIBUTE_FORMAT(printf, 3, 0);
PHPAPI zend_string *vstrpprintf(size_t max_len, const char *format, va_list ap);
PHPAPI zend_string *strpprintf(size_t max_len, const char *format, ...);
END_EXTERN_C()
#endif /* SNPRINTF_H */