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.
This commit is contained in:
Nikita Popov 2016-12-18 17:53:27 +01:00
parent c7742e280a
commit 5fc9aa9a95
5 changed files with 71 additions and 68 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
/* }}} */

View File

@ -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 */