From 5fc9aa9a9509727a55ec5badae9df1a9617be6a1 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 18 Dec 2016 17:53:27 +0100 Subject: [PATCH] Make printf_to_smart_str(ing) the primitive printf operation vs(tr)pprintf is now implemented in Zend on top of printf_to_smart_str(int), which is provided as a utility function. This allows us to efficiently printf to the end of a smart string. --- Zend/zend.c | 56 +++++++++++++++++++++++++++++++++++++++++++++---- Zend/zend.h | 11 ++++++---- main/main.c | 4 ++-- main/spprintf.c | 45 ++++----------------------------------- main/spprintf.h | 23 ++++++-------------- 5 files changed, 71 insertions(+), 68 deletions(-) diff --git a/Zend/zend.c b/Zend/zend.c index 4dadcd73b7..dc0f1e9c75 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -32,6 +32,7 @@ #include "zend_dtrace.h" #include "zend_virtual_cwd.h" #include "zend_smart_str.h" +#include "zend_smart_string.h" #ifdef ZTS # define GLOBAL_FUNCTION_TABLE global_function_table @@ -54,8 +55,8 @@ ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle ZEND_API void (*zend_ticks_function)(int ticks); ZEND_API void (*zend_interrupt_function)(zend_execute_data *execute_data); ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args); -size_t (*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); +void (*zend_printf_to_smart_string)(smart_string *buf, const char *format, va_list ap); +void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_list ap); ZEND_API char *(*zend_getenv)(char *name, size_t name_len); ZEND_API zend_string *(*zend_resolve_path)(const char *filename, int filename_len); @@ -159,6 +160,34 @@ static uint32_t zend_version_info_length; #define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) 1998-2016 Zend Technologies\n" #define PRINT_ZVAL_INDENT 4 +ZEND_API size_t zend_vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */ +{ + smart_string buf = {0}; + + /* since there are places where (v)spprintf called without checking for null, + a bit of defensive coding here */ + if (!pbuf) { + return 0; + } + + zend_printf_to_smart_string(&buf, format, ap); + + if (max_len && buf.len > max_len) { + buf.len = max_len; + } + + smart_string_0(&buf); + + if (buf.c) { + *pbuf = buf.c; + return buf.len; + } else { + *pbuf = estrndup("", 0); + return 0; + } +} +/* }}} */ + ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) /* {{{ */ { va_list arg; @@ -171,6 +200,25 @@ ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format } /* }}} */ +ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */ +{ + smart_str buf = {0}; + + zend_printf_to_smart_str(&buf, format, ap); + + if (!buf.s) { + return ZSTR_EMPTY_ALLOC(); + } + + if (max_len && ZSTR_LEN(buf.s) > max_len) { + ZSTR_LEN(buf.s) = max_len; + } + + smart_str_0(&buf); + return buf.s; +} +/* }}} */ + ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) /* {{{ */ { va_list arg; @@ -708,8 +756,8 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) / zend_get_configuration_directive_p = utility_functions->get_configuration_directive; 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_printf_to_smart_string = utility_functions->printf_to_smart_string_function; + zend_printf_to_smart_str = utility_functions->printf_to_smart_str_function; zend_getenv = utility_functions->getenv_function; zend_resolve_path = utility_functions->resolve_path_function; diff --git a/Zend/zend.h b/Zend/zend.h index e398dac9a1..7ed61d5bee 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -38,6 +38,7 @@ #include "zend_iterators.h" #include "zend_stream.h" #include "zend_smart_str_public.h" +#include "zend_smart_string_public.h" #include "zend_signal.h" #define HANDLE_BLOCK_INTERRUPTIONS() ZEND_SIGNAL_BLOCK_INTERRUPTIONS() @@ -185,8 +186,8 @@ typedef struct _zend_utility_functions { void (*ticks_function)(int ticks); void (*on_timeout)(int seconds); int (*stream_open_function)(const char *filename, zend_file_handle *handle); - size_t (*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); + void (*printf_to_smart_string_function)(smart_string *buf, const char *format, va_list ap); + void (*printf_to_smart_str_function)(smart_str *buf, const char *format, va_list ap); char *(*getenv_function)(char *name, size_t name_len); zend_string *(*resolve_path_function)(const char *filename, int filename_len); } zend_utility_functions; @@ -226,7 +227,9 @@ void zend_set_utility_values(zend_utility_values *utility_values); ZEND_API ZEND_COLD void _zend_bailout(char *filename, uint32_t lineno); +ZEND_API size_t zend_vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap); ZEND_API size_t zend_spprintf(char **message, size_t max_len, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 3, 4); +ZEND_API zend_string *zend_vstrpprintf(size_t max_len, const char *format, va_list ap); ZEND_API zend_string *zend_strpprintf(size_t max_len, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); ZEND_API char *get_zend_version(void); @@ -263,8 +266,8 @@ extern ZEND_API void (*zend_interrupt_function)(zend_execute_data *execute_data) extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0); extern ZEND_API void (*zend_on_timeout)(int seconds); extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle); -extern size_t (*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 void (*zend_printf_to_smart_string)(smart_string *buf, const char *format, va_list ap); +extern void (*zend_printf_to_smart_str)(smart_str *buf, const char *format, va_list ap); extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len); extern ZEND_API zend_string *(*zend_resolve_path)(const char *filename, int filename_len); diff --git a/main/main.c b/main/main.c index 361b356d44..afa4313570 100644 --- a/main/main.c +++ b/main/main.c @@ -2114,8 +2114,8 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod zuf.ticks_function = php_run_ticks; zuf.on_timeout = php_on_timeout; zuf.stream_open_function = php_stream_open_for_zend; - zuf.vspprintf_function = vspprintf; - zuf.vstrpprintf_function = vstrpprintf; + zuf.printf_to_smart_string_function = php_printf_to_smart_string; + zuf.printf_to_smart_str_function = php_printf_to_smart_str; zuf.getenv_function = sapi_getenv; zuf.resolve_path_function = php_resolve_path_for_zend; zend_startup(&zuf, NULL); diff --git a/main/spprintf.c b/main/spprintf.c index 8f141c9978..0e0784663c 100644 --- a/main/spprintf.c +++ b/main/spprintf.c @@ -827,52 +827,15 @@ skip_output: } /* }}} */ -/* - * This is the general purpose conversion function. - */ -PHPAPI size_t vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */ +PHPAPI void php_printf_to_smart_string(smart_string *buf, const char *format, va_list ap) /* {{{ */ { - smart_string buf = {0}; - - /* since there are places where (v)spprintf called without checking for null, - a bit of defensive coding here */ - if(!pbuf) { - return 0; - } - xbuf_format_converter(&buf, 1, format, ap); - - if (max_len && buf.len > max_len) { - buf.len = max_len; - } - - smart_string_0(&buf); - - if (buf.c) { - *pbuf = buf.c; - return buf.len; - } else { - *pbuf = estrndup("", 0); - return 0; - } + xbuf_format_converter(buf, 1, format, ap); } /* }}} */ -PHPAPI zend_string *vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */ +PHPAPI void php_printf_to_smart_str(smart_str *buf, const char *format, va_list ap) /* {{{ */ { - smart_str buf = {0}; - - xbuf_format_converter(&buf, 0, format, ap); - - if (!buf.s) { - return ZSTR_EMPTY_ALLOC(); - } - - if (max_len && ZSTR_LEN(buf.s) > max_len) { - ZSTR_LEN(buf.s) = max_len; - } - - smart_str_0(&buf); - return buf.s; + xbuf_format_converter(buf, 0, format, ap); } /* }}} */ diff --git a/main/spprintf.h b/main/spprintf.h index db684c2be8..d69bffa05b 100644 --- a/main/spprintf.h +++ b/main/spprintf.h @@ -16,33 +16,22 @@ +----------------------------------------------------------------------+ */ -/* $Id$ */ - -/* - -The pbuf parameter of all spprintf version receives a pointer to the allocated -buffer. This buffer must be freed manually after usage using efree() function. -The buffer will always be terminated by a zero character. When pbuf is NULL -the function can be used to calculate the required size of the buffer but for -that purpose snprintf is faster. When both pbuf and the return value are 0 -than you are out of memory. - -There is also snprintf: See difference explained in snprintf.h - -*/ - #ifndef SPPRINTF_H #define SPPRINTF_H #include "snprintf.h" +#include "zend_smart_str_public.h" +#include "zend_smart_string_public.h" BEGIN_EXTERN_C() -PHPAPI size_t 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) PHP_ATTRIBUTE_FORMAT(printf, 2, 0); +PHPAPI void php_printf_to_smart_string(smart_string *buf, const char *format, va_list ap); +PHPAPI void php_printf_to_smart_str(smart_str *buf, const char *format, va_list ap); END_EXTERN_C() #define spprintf zend_spprintf #define strpprintf zend_strpprintf +#define vspprintf zend_vspprintf +#define vstrpprintf zend_vstrpprintf #endif /* SNPRINTF_H */ -- 2.40.0