Convert serializer to smart_str.. avoids lots of sprintf's and

copying of data.
This commit is contained in:
Sascha Schumann 2001-08-03 07:25:27 +00:00
parent 2ec440078a
commit 4dfa91543c
5 changed files with 104 additions and 103 deletions

View file

@ -279,36 +279,26 @@ int php_get_session_var(char *name, size_t namelen, zval ***state_var TSRMLS_DC)
PS_SERIALIZER_ENCODE_FUNC(php_binary)
{
zval *buf;
unsigned char strbuf[MAX_STR + 1];
smart_str buf = {0};
php_serialize_data_t var_hash;
PS_ENCODE_VARS;
buf = ecalloc(sizeof(*buf), 1);
Z_TYPE_P(buf) = IS_STRING;
buf->refcount++;
PHP_VAR_SERIALIZE_INIT(var_hash);
PS_ENCODE_LOOP(
if (key_length > PS_BIN_MAX) continue;
strbuf[0] = (unsigned char) key_length;
memcpy(strbuf + 1, key, key_length);
smart_str_appendc(&buf, key_length);
smart_str_appendl(&buf, key, key_length);
STR_CAT(buf, strbuf, key_length + 1);
php_var_serialize(buf, struc, &var_hash);
php_var_serialize(&buf, struc, &var_hash);
} else {
if (key_length > PS_BIN_MAX) continue;
strbuf[0] = (unsigned char) (key_length & PS_BIN_UNDEF);
memcpy(strbuf + 1, key, key_length);
STR_CAT(buf, strbuf, key_length + 1);
smart_str_appendc(&buf, (key_length & PS_BIN_UNDEF));
smart_str_appendl(&buf, key, key_length);
);
if (newlen) *newlen = Z_STRLEN_P(buf);
*newstr = Z_STRVAL_P(buf);
efree(buf);
if (newlen) *newlen = buf.len;
*newstr = buf.c;
PHP_VAR_SERIALIZE_DESTROY(var_hash);
return SUCCESS;
@ -355,36 +345,27 @@ PS_SERIALIZER_DECODE_FUNC(php_binary)
PS_SERIALIZER_ENCODE_FUNC(php)
{
zval *buf;
char strbuf[MAX_STR + 1];
smart_str buf = {0};
php_serialize_data_t var_hash;
PS_ENCODE_VARS;
buf = ecalloc(sizeof(*buf), 1);
Z_TYPE_P(buf) = IS_STRING;
buf->refcount++;
PHP_VAR_SERIALIZE_INIT(var_hash);
PS_ENCODE_LOOP(
if (key_length + 1 > MAX_STR) continue;
memcpy(strbuf, key, key_length);
strbuf[key_length] = PS_DELIMITER;
STR_CAT(buf, strbuf, key_length + 1);
smart_str_appendl(&buf, key, key_length);
smart_str_appendc(&buf, PS_DELIMITER);
php_var_serialize(buf, struc, &var_hash);
php_var_serialize(&buf, struc, &var_hash);
} else {
if (key_length + 2 > MAX_STR) continue;
strbuf[0] = PS_UNDEF_MARKER;
memcpy(strbuf + 1, key, key_length);
strbuf[key_length + 1] = PS_DELIMITER;
STR_CAT(buf, strbuf, key_length + 2);
smart_str_appendc(&buf, PS_UNDEF_MARKER);
smart_str_appendl(&buf, key, key_length);
smart_str_appendc(&buf, PS_DELIMITER);
);
if (newlen) *newlen = Z_STRLEN_P(buf);
*newstr = Z_STRVAL_P(buf);
efree(buf);
if (newlen) *newlen = buf.len;
*newstr = buf.c;
PHP_VAR_SERIALIZE_DESTROY(var_hash);
return SUCCESS;

View file

@ -46,6 +46,7 @@
#define smart_str_free(s) smart_str_free_ex(s, 0)
#define smart_str_appendl(dest,src,len) smart_str_appendl_ex(dest,src,len,0)
#define smart_str_append(dest, src) smart_str_append_ex(dest,src,0)
#define smart_str_append_long(dest, val) smart_str_append_long_ex(dest,val,0)
static inline void smart_str_appendc_ex(smart_str *dest, char c, int what)
{
@ -75,6 +76,36 @@ static inline void smart_str_appendl_ex(smart_str *dest, const char *src, size_t
dest->len = newlen;
}
static inline char *smart_str_print_long(char *buf, long num)
{
char *p = buf;
long tmp = 0;
if (num < 0) {
num = -num;
*p++ = '-';
}
while (num > 0) {
tmp = tmp * 10 + (num % 10);
num /= 10;
}
do {
*p++ = (tmp % 10) + '0';
tmp /= 10;
} while (tmp > 0);
return p;
}
static inline void smart_str_append_long_ex(smart_str *dest, long num, int type)
{
char buf[32];
char *p = smart_str_print_long(buf, num);
smart_str_appendl_ex(dest, buf, p - buf, type);
}
static inline void smart_str_append_ex(smart_str *dest, smart_str *src, int what)
{
smart_str_appendl_ex(dest, src->c, src->len, what);

View file

@ -21,6 +21,8 @@
#ifndef PHP_VAR_H
#define PHP_VAR_H
#include "ext/standard/php_smart_str_public.h"
PHP_FUNCTION(var_dump);
PHP_FUNCTION(serialize);
PHP_FUNCTION(unserialize);
@ -30,7 +32,7 @@ void php_var_dump(zval **struc, int level);
/* typdef HashTable php_serialize_data_t; */
#define php_serialize_data_t HashTable
PHPAPI void php_var_serialize(zval *buf, zval **struc, php_serialize_data_t *var_hash);
PHPAPI void php_var_serialize(smart_str *buf, zval **struc, php_serialize_data_t *var_hash);
PHPAPI int php_var_unserialize(zval **rval, const char **p, const char *max, php_serialize_data_t *var_hash);
#define PHP_VAR_SERIALIZE_INIT(var_hash) \

View file

@ -30,6 +30,7 @@
#include "php.h"
#include "php_string.h"
#include "php_var.h"
#include "php_smart_str.h"
#include "basic_functions.h"
#include "php_incomplete_class.h"
@ -137,34 +138,17 @@ PHP_FUNCTION(var_dump)
/* }}} */
/* {{{ php_var_dump */
#define STR_CAT(P,S,I) {\
zval *__p = (P);\
ulong __i = Z_STRLEN_P(__p);\
Z_STRLEN_P(__p) += (I);\
if (Z_STRVAL_P(__p)) {\
Z_STRVAL_P(__p) = (char *)erealloc(Z_STRVAL_P(__p), Z_STRLEN_P(__p) + 1);\
} else {\
Z_STRVAL_P(__p) = emalloc(Z_STRLEN_P(__p) + 1);\
*Z_STRVAL_P(__p) = 0;\
}\
strcat(Z_STRVAL_P(__p) + __i, (S));\
}
/* }}} */
/* {{{ php_var_serialize */
static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old)
{
ulong var_no;
char id[sizeof(void *)*2+3];
char id[32], *p;
snprintf(id,sizeof(id)-1, "%p", var);
id[sizeof(id)-1]='\0';
p = smart_str_print_long(id, (long) var);
*p = '\0';
if(var_old && zend_hash_find(var_hash, id, strlen(id), var_old) == SUCCESS) {
if(var_old && zend_hash_find(var_hash, id, p - id, var_old) == SUCCESS) {
if(!var->is_ref) {
/* we still need to bump up the counter, since non-refs will
be counted separately by unserializer */
@ -175,11 +159,11 @@ static inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old
}
var_no = zend_hash_num_elements(var_hash)+1; /* +1 because otherwise hash will think we are trying to store NULL pointer */
zend_hash_add(var_hash, id, strlen(id), &var_no, sizeof(var_no), NULL);
zend_hash_add(var_hash, id, p - id, &var_no, sizeof(var_no), NULL);
return SUCCESS;
}
PHPAPI void php_var_serialize(zval *buf, zval **struc, HashTable *var_hash)
PHPAPI void php_var_serialize(smart_str *buf, zval **struc, HashTable *var_hash)
{
char s[256];
ulong slen;
@ -189,47 +173,41 @@ PHPAPI void php_var_serialize(zval *buf, zval **struc, HashTable *var_hash)
TSRMLS_FETCH();
if(var_hash != NULL && php_add_var_hash(var_hash,*struc,(void *)&var_already) == FAILURE && (*struc)->is_ref) {
slen = sprintf(s,"R:%ld;",*var_already);
STR_CAT(buf, s, slen);
smart_str_appendl(buf, "R:", 2);
smart_str_append_long(buf, *var_already);
smart_str_appendc(buf, ';');
return;
}
switch ((*struc)->type) {
case IS_BOOL:
slen = sprintf(s, "b:%ld;", Z_LVAL_PP(struc));
STR_CAT(buf, s, slen);
smart_str_appendl(buf, "b:", 2);
smart_str_append_long(buf, Z_LVAL_PP(struc));
smart_str_appendc(buf, ';');
return;
case IS_NULL:
STR_CAT(buf, "N;", 2);
smart_str_appendl(buf, "N;", 2);
return;
case IS_LONG:
slen = sprintf(s, "i:%ld;", Z_LVAL_PP(struc));
STR_CAT(buf, s, slen);
smart_str_appendl(buf, "i:", 2);
smart_str_append_long(buf, Z_LVAL_PP(struc));
smart_str_appendc(buf, ';');
return;
case IS_DOUBLE: {
slen = sprintf(s, "d:%.*G;",(int) EG(precision), Z_DVAL_PP(struc));
STR_CAT(buf, s, slen);
}
case IS_DOUBLE:
slen = sprintf(s, "d:%.*G;",(int) EG(precision), Z_DVAL_PP(struc));
smart_str_appendl(buf, s, slen);
return;
case IS_STRING:{
char *p;
i = buf->value.str.len;
slen = sprintf(s, "s:%d:\"", Z_STRLEN_PP(struc));
STR_CAT(buf, s, slen + Z_STRLEN_PP(struc) + 2);
p = Z_STRVAL_P(buf) + i + slen;
if (Z_STRLEN_PP(struc) > 0) {
memcpy(p, Z_STRVAL_PP(struc), Z_STRLEN_PP(struc));
p += Z_STRLEN_PP(struc);
}
*p++ = '\"';
*p++ = ';';
*p = 0;
}
case IS_STRING:
smart_str_appendl(buf, "s:", 2);
smart_str_append_long(buf, Z_STRLEN_PP(struc));
smart_str_appendl(buf, ":\"", 2);
smart_str_appendl(buf, Z_STRVAL_PP(struc), Z_STRLEN_PP(struc));
smart_str_appendl(buf, "\";", 2);
return;
case IS_OBJECT: {
zval *retval_ptr = NULL;
@ -240,17 +218,22 @@ PHPAPI void php_var_serialize(zval *buf, zval **struc, HashTable *var_hash)
MAKE_STD_ZVAL(fname);
ZVAL_STRING(fname,"__sleep",1);
res = call_user_function_ex(CG(function_table), struc, fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
res = call_user_function_ex(CG(function_table), struc, fname, &retval_ptr, 0, 0, 1, NULL TSRMLS_CC);
if (res == SUCCESS) {
if (retval_ptr && HASH_OF(retval_ptr)) {
int count = zend_hash_num_elements(HASH_OF(retval_ptr));
PHP_SET_CLASS_ATTRIBUTES(*struc);
slen = sprintf(s, "O:%d:\"%s\":%d:{",name_len,class_name, count);
smart_str_appendl(buf, "O:", 2);
smart_str_append_long(buf, name_len);
smart_str_appendl(buf, ":\"", 2);
smart_str_appendl(buf, class_name, name_len);
smart_str_appendl(buf, "\":", 2);
smart_str_append_long(buf, count);
smart_str_appendl(buf, ":{", 2);
PHP_CLEANUP_CLASS_ATTRIBUTES();
STR_CAT(buf, s, slen);
if (count > 0) {
char *key;
zval **d,**name;
@ -272,11 +255,11 @@ PHPAPI void php_var_serialize(zval *buf, zval **struc, HashTable *var_hash)
if (zend_hash_find(Z_OBJPROP_PP(struc), Z_STRVAL_PP(name), Z_STRLEN_PP(name)+1, (void*)&d) == SUCCESS) {
php_var_serialize(buf, name, NULL);
php_var_serialize(buf,d,var_hash);
php_var_serialize(buf, d, var_hash);
}
}
}
STR_CAT(buf, "}", 1);
smart_str_appendc(buf, '}');
}
} else {
zval_dtor(fname);
@ -301,15 +284,20 @@ PHPAPI void php_var_serialize(zval *buf, zval **struc, HashTable *var_hash)
myht = HASH_OF(*struc);
i = zend_hash_num_elements(myht);
if ((*struc)->type == IS_ARRAY) {
slen = sprintf(s, "a:%d:{", i);
smart_str_appendl(buf, "a:", 2);
} else {
PHP_CLASS_ATTRIBUTES;
PHP_SET_CLASS_ATTRIBUTES(*struc);
slen = sprintf(s, "O:%d:\"%s\":%d:{",name_len,class_name,i);
smart_str_appendl(buf, "O:", 2);
smart_str_append_long(buf, name_len);
smart_str_appendl(buf, ":\"", 2);
smart_str_appendl(buf, class_name, name_len);
smart_str_appendl(buf, "\":", 2);
PHP_CLEANUP_CLASS_ATTRIBUTES();
}
STR_CAT(buf, s, slen);
smart_str_append_long(buf, i);
smart_str_appendl(buf, ":{", 2);
if (i > 0) {
char *key;
zval **data,*d;
@ -342,10 +330,10 @@ PHPAPI void php_var_serialize(zval *buf, zval **struc, HashTable *var_hash)
php_var_serialize(buf, data, var_hash);
}
}
STR_CAT(buf, "}", 1);
smart_str_appendc(buf, '}');
return;
default:
STR_CAT(buf, "i:0;", 4);
smart_str_appendl(buf, "i:0;", 4);
return;
}
}
@ -605,6 +593,7 @@ PHP_FUNCTION(serialize)
{
zval **struc;
php_serialize_data_t var_hash;
smart_str buf = {0};
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &struc) == FAILURE) {
WRONG_PARAM_COUNT;
@ -615,8 +604,9 @@ PHP_FUNCTION(serialize)
return_value->value.str.len = 0;
PHP_VAR_SERIALIZE_INIT(var_hash);
php_var_serialize(return_value, struc, &var_hash);
php_var_serialize(&buf, struc, &var_hash);
PHP_VAR_SERIALIZE_DESTROY(var_hash);
RETVAL_STRINGL(buf.c, buf.len, 0);
}
/* }}} */

View file

@ -222,7 +222,7 @@ PHP_FUNCTION(shm_put_var)
long key, id;
sysvshm_shm *shm_list_ptr;
int type;
pval shm_var;
smart_str shm_var = {0};
int ret;
php_serialize_data_t var_hash;
@ -243,17 +243,14 @@ PHP_FUNCTION(shm_put_var)
/* setup string-variable and serialize */
shm_var.type=IS_STRING;
shm_var.value.str.len=0;
shm_var.value.str.val=0;
PHP_VAR_SERIALIZE_INIT(var_hash);
php_var_serialize(&shm_var,arg_var,&var_hash);
PHP_VAR_SERIALIZE_DESTROY(var_hash);
/* insert serialized variable into shared memory */
ret=php_put_shm_data(shm_list_ptr->ptr,key,shm_var.value.str.val,shm_var.value.str.len);
ret=php_put_shm_data(shm_list_ptr->ptr,key,shm_var.c,shm_var.len);
/* free string */
efree(shm_var.value.str.val);
smart_str_free(&shm_var);
if(ret==-1) {
php_error(E_WARNING, "not enough shared memory left");