]> granicus.if.org Git - php/commitdiff
Added vstrpprintf strpprintf to avoid duplicate string
authorXinchen Hui <laruence@php.net>
Fri, 9 May 2014 16:21:49 +0000 (00:21 +0800)
committerXinchen Hui <laruence@php.net>
Fri, 9 May 2014 16:21:49 +0000 (00:21 +0800)
(the function name maybe improvement)

Zend/zend.c
Zend/zend.h
Zend/zend_closures.c
Zend/zend_exceptions.c
Zend/zend_exceptions.h
Zend/zend_operators.c
main/main.c
main/spprintf.c
main/spprintf.h

index 97afdb936fd5cc70d40b660ee0bb00d63afaaa8c..eccd477f77857b6e93264ad2a5e86637f15ff73d 100644 (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;
 
index cabe64a56aa388b9f72d072dd90b07716aff24f1..278018154435a4fb75da21096b11867902e77551 100644 (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);
 
index 9d48dab9f26bf936f521d92ea7fa7ba49efe7e8f..1eae481829c9b450515c179eaa4994641d3f846f 100644 (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);
index 8b897961792654cc8116f3e2157371beed249808..ae0ae834e4387090eef1f2f0dc6a4ea82bdb4638 100644 (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);
 }
 /* }}} */
 
index 24113d6f8d8163f7180b9218ff7e2ff4977debd0..a7997867517d15b5dd6c1861a3e7649917a2aa1a 100644 (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()
 
index 9cf0497d220efcf87aa6ad4f3a783098878d818c..4c9db85262100266f0e216639c7dd8a373627fe1 100644 (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);
 }
 /* }}} */
 
index ebe0655d3a2cacd599abd2632a6f39ca7bcdc532..87e0b39c6c0b1b0c5a4c6c91dfcf2664f718a2c9 100644 (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);
index 57548a5fcbd736df2a1baf727aab770b2e14782c..50ebc3b31e0ab1134750a5da12daf7a74dd2b9fe 100644 (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
index 813bbde01ae208c3d945dea361000fbb160bf1bc..ae26a3b9ec6bafefc845b9f52a1ebc79b6336eef 100644 (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 */