]> granicus.if.org Git - php/commitdiff
Add support for serializing references.
authorStanislav Malyshev <stas@php.net>
Mon, 30 Oct 2000 17:10:06 +0000 (17:10 +0000)
committerStanislav Malyshev <stas@php.net>
Mon, 30 Oct 2000 17:10:06 +0000 (17:10 +0000)
@- Add support for serializing references (Stas)
# WDDX and shared memory functions not covered yet

ext/session/session.c
ext/standard/php_var.h
ext/standard/var.c
ext/sysvshm/sysvshm.c

index 4be69bfd9f51aa064b8e886b7d3bae4900a25581..1ed71dace093a8ad807c1b13bbfadd32685668cc 100644 (file)
@@ -248,12 +248,15 @@ PS_SERIALIZER_ENCODE_FUNC(php_binary)
 {
        zval *buf;
        char strbuf[MAX_STR + 1];
+       php_serialize_data_t var_hash;
        ENCODE_VARS;
 
        buf = ecalloc(sizeof(*buf), 1);
        Z_TYPE_P(buf) = IS_STRING;
        buf->refcount++;
 
+       PHP_VAR_SERIALIZE_INIT(var_hash);
+
        ENCODE_LOOP(
                        size_t slen = strlen(key);
 
@@ -262,7 +265,7 @@ PS_SERIALIZER_ENCODE_FUNC(php_binary)
                        memcpy(strbuf + 1, key, slen);
                        
                        STR_CAT(buf, strbuf, slen + 1);
-                       php_var_serialize(buf, struc);
+                       php_var_serialize(buf, struc, &var_hash);
                } else {
                        size_t slen = strlen(key);
 
@@ -276,6 +279,7 @@ PS_SERIALIZER_ENCODE_FUNC(php_binary)
        if (newlen) *newlen = Z_STRLEN_P(buf);
        *newstr = Z_STRVAL_P(buf);
        efree(buf);
+       PHP_VAR_SERIALIZE_DESTROY(var_hash);
 
        return SUCCESS;
 }
@@ -288,6 +292,9 @@ PS_SERIALIZER_DECODE_FUNC(php_binary)
        zval *current;
        int namelen;
        int has_value;
+       php_serialize_data_t var_hash;
+
+       PHP_VAR_UNSERIALIZE_INIT(var_hash);
 
        current = (zval *) ecalloc(sizeof(zval), 1);
        for (p = val; p < endptr; ) {
@@ -299,7 +306,7 @@ PS_SERIALIZER_DECODE_FUNC(php_binary)
                p += namelen + 1;
                
                if (has_value) {
-                       if (php_var_unserialize(&current, &p, endptr)) {
+                       if (php_var_unserialize(&current, &p, endptr, &var_hash)) {
                                php_set_session_var(name, namelen, current PSLS_CC);
                                zval_dtor(current);
                        }
@@ -308,6 +315,7 @@ PS_SERIALIZER_DECODE_FUNC(php_binary)
                efree(name);
        }
        efree(current);
+       PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
 
        return SUCCESS;
 }
@@ -319,12 +327,15 @@ PS_SERIALIZER_ENCODE_FUNC(php)
 {
        zval *buf;
        char strbuf[MAX_STR + 1];
+       php_serialize_data_t var_hash;
        ENCODE_VARS;
 
        buf = ecalloc(sizeof(*buf), 1);
        Z_TYPE_P(buf) = IS_STRING;
        buf->refcount++;
 
+       PHP_VAR_SERIALIZE_INIT(var_hash);
+
        ENCODE_LOOP(
                        size_t slen = strlen(key);
 
@@ -333,7 +344,7 @@ PS_SERIALIZER_ENCODE_FUNC(php)
                        strbuf[slen] = PS_DELIMITER;
                        STR_CAT(buf, strbuf, slen + 1);
                        
-                       php_var_serialize(buf, struc);
+                       php_var_serialize(buf, struc, &var_hash);
                } else {
                        size_t slen = strlen(key);
 
@@ -349,6 +360,7 @@ PS_SERIALIZER_ENCODE_FUNC(php)
        *newstr = Z_STRVAL_P(buf);
        efree(buf);
 
+       PHP_VAR_SERIALIZE_DESTROY(var_hash);
        return SUCCESS;
 }
 
@@ -360,6 +372,9 @@ PS_SERIALIZER_DECODE_FUNC(php)
        zval *current;
        int namelen;
        int has_value;
+       php_serialize_data_t var_hash;
+
+       PHP_VAR_UNSERIALIZE_INIT(var_hash);
 
        current = (zval *) ecalloc(sizeof(zval), 1);
        for (p = q = val; (p < endptr) && (q = memchr(p, PS_DELIMITER, endptr - p)); p = q) {
@@ -375,7 +390,7 @@ PS_SERIALIZER_DECODE_FUNC(php)
                q++;
                
                if (has_value) {
-                       if (php_var_unserialize(&current, &q, endptr)) {
+                       if (php_var_unserialize(&current, &q, endptr, &var_hash)) {
                                php_set_session_var(name, namelen, current PSLS_CC);
                                zval_dtor(current);
                        }
@@ -385,6 +400,7 @@ PS_SERIALIZER_DECODE_FUNC(php)
        }
        efree(current);
 
+       PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
        return SUCCESS;
 }
 
index 71ca6f3c8f598a1f9cde4ec3f28afeb98acb0fcb..8ce3316e2ba213a1ca58af00231223d3b95617e4 100644 (file)
@@ -26,8 +26,22 @@ PHP_FUNCTION(serialize);
 PHP_FUNCTION(unserialize);
 
 void php_var_dump(pval **struc, int level);
-void php_var_serialize(pval *buf, pval **struc);
-int php_var_unserialize(pval **rval, const char **p, const char *max);
+
+/* typdef HashTable php_serialize_data_t; */
+#define php_serialize_data_t HashTable
+
+void php_var_serialize(pval *buf, pval **struc, php_serialize_data_t *var_hash);
+int php_var_unserialize(pval **rval, const char **p, const char *max, php_serialize_data_t *var_hash);
+
+#define PHP_VAR_SERIALIZE_INIT(var_hash) \
+   zend_hash_init(&(var_hash),10,NULL,NULL,0)
+#define PHP_VAR_SERIALIZE_DESTROY(var_hash) \
+   zend_hash_destroy(&(var_hash))
+
+#define PHP_VAR_UNSERIALIZE_INIT(var_hash) \
+   zend_hash_init(&(var_hash),10,NULL,NULL,0)
+#define PHP_VAR_UNSERIALIZE_DESTROY(var_hash) \
+   zend_hash_destroy(&(var_hash))
 
 PHPAPI zend_class_entry *php_create_empty_class(char *class_name,int len);
 
index 04b7d5ba8ee3e9da9ad99f847d04f59349eb8f44..d78bf5157707c5237eb9fde96451f8eed7c7ba3c 100644 (file)
@@ -95,7 +95,7 @@ head_done:
                                php_printf("%*c", level-1, ' ');
                        }
                        PUTS("}\n");
-                       break;  
+                       break;
                case IS_RESOURCE: {
                        char *type_name;
                        type_name = zend_rsrc_list_get_rsrc_type((*struc)->value.lval);
@@ -154,14 +154,36 @@ PHP_FUNCTION(var_dump)
 /* }}} */
 /* {{{ php_var_serialize */
 
-void php_var_serialize(pval *buf, pval **struc)
+inline int php_add_var_hash(HashTable *var_hash, zval *var, void *var_old) {
+       ulong var_no;
+       char id[sizeof(void *)*2+3];
+
+       snprintf(id,sizeof(id)-1,"%p",var);
+       id[sizeof(id)-1]='\0';
+       if(var_old && zend_hash_find(var_hash,id,sizeof(void *)*2,var_old) == SUCCESS) {
+               return FAILURE;
+       }
+       
+       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,sizeof(void *)*2,&var_no,sizeof(var_no),NULL);
+       return SUCCESS;
+}
+
+void php_var_serialize(pval *buf, pval **struc, HashTable *var_hash)
 {
        char s[256];
        ulong slen;
        int i;
+       ulong *var_already;
        HashTable *myht;
        BLS_FETCH();
 
+       if(var_hash != NULL && php_add_var_hash(var_hash,*struc,(void *)&var_already) == FAILURE) {
+               slen = sprintf(s,"R:%ld;",*var_already);
+               STR_CAT(buf, s, slen);
+               return;
+       }
+
        switch ((*struc)->type) {
                case IS_BOOL:
                        slen = sprintf(s, "b:%ld;", (*struc)->value.lval);
@@ -241,10 +263,10 @@ void php_var_serialize(pval *buf, pval **struc)
                                                                        continue;
                                                                }
 
-                                                               php_var_serialize(buf, name);
+                                                               php_var_serialize(buf, name, NULL);
                                                                
                                                                if (zend_hash_find((*struc)->value.obj.properties,(*name)->value.str.val,(*name)->value.str.len+1,(void*)&d) == SUCCESS) {
-                                                                       php_var_serialize(buf,d);       
+                                                                       php_var_serialize(buf,d,var_hash);      
                                                                }
                                                        }
                                                }
@@ -294,18 +316,18 @@ void php_var_serialize(pval *buf, pval **struc)
                                        if ((i = zend_hash_get_current_key_ex(myht, &key, NULL, &index, &pos)) == HASH_KEY_NON_EXISTANT) {
                                                break;
                                        }
-                                       if (zend_hash_get_current_data_ex(myht, (void **) (&data), &pos) != SUCCESS || !data || ((*data) == (*struc))) {
+                                       if (zend_hash_get_current_data_ex(myht, (void **) (&data), &pos) != SUCCESS || !data /* || ((*data) == (*struc)) */) {
                                                if (i == HASH_KEY_IS_STRING)
                                                        efree(key);
                                                continue;
                                        }
 
                                        switch (i) {
-                                               case HASH_KEY_IS_LONG:
+                                         case HASH_KEY_IS_LONG:
                                                        MAKE_STD_ZVAL(d);       
                                                        d->type = IS_LONG;
                                                        d->value.lval = index;
-                                                       php_var_serialize(buf, &d);
+                                                       php_var_serialize(buf, &d, NULL);
                                                        FREE_ZVAL(d);
                                                        break;
                                                case HASH_KEY_IS_STRING:
@@ -313,12 +335,12 @@ void php_var_serialize(pval *buf, pval **struc)
                                                        d->type = IS_STRING;
                                                        d->value.str.val = key;
                                                        d->value.str.len = strlen(key);
-                                                       php_var_serialize(buf, &d);
+                                                       php_var_serialize(buf, &d, NULL);
                                                        efree(key);
                                                        FREE_ZVAL(d);
                                                        break;
                                        }
-                                       php_var_serialize(buf, data);
+                                       php_var_serialize(buf, data, var_hash);
                                }
                        }
                        STR_CAT(buf, "}", 1);
@@ -333,17 +355,50 @@ void php_var_serialize(pval *buf, pval **struc)
 /* }}} */
 /* {{{ php_var_dump */
 
-int php_var_unserialize(pval **rval, const char **p, const char *max)
+int php_var_unserialize(pval **rval, const char **p, const char *max, HashTable *var_hash)
 {
        const char *q;
        char *str;
        int i;
        char cur;
+       ulong id;
        HashTable *myht;
+       pval **rval_ref;
+
        ELS_FETCH();
        BLS_FETCH();
 
+       if(var_hash) {
+               zend_hash_next_index_insert(var_hash, rval, sizeof(*rval), NULL);
+       }
+
        switch (cur = **p) {
+           case 'R':
+                       if (*((*p) + 1) != ':') {
+                               return 0;
+                       }
+                       q = *p;
+                       while (**p && **p != ';') {
+                               (*p)++;
+                       }
+                       if (**p != ';') {
+                               return 0;
+                       }
+                       (*p)++;
+                       id = atol(q + 2)-1; /* count starts with 1 */
+                       if(!var_hash) {
+                               return 0;
+                       }
+                       if(zend_hash_index_find(var_hash, id, (void *)&rval_ref) != SUCCESS) {
+                               return 0;
+                       }
+                       zval_dtor(*rval);
+                       FREE_ZVAL(*rval);
+                       *rval = *rval_ref;
+                       (*rval)->refcount++;
+                       (*rval)->is_ref = 1;
+                       return 1;
+
                case 'N':
                        if (*((*p) + 1) != ';') {
                                return 0;
@@ -504,13 +559,13 @@ int php_var_unserialize(pval **rval, const char **p, const char *max)
                                ALLOC_INIT_ZVAL(key);
                                ALLOC_INIT_ZVAL(data);
 
-                               if (!php_var_unserialize(&key, p, max)) {
+                               if (!php_var_unserialize(&key, p, max, NULL)) {
                                        zval_dtor(key);
                                        FREE_ZVAL(key);
                                        FREE_ZVAL(data);
                                        return 0;
                                }
-                               if (!php_var_unserialize(&data, p, max)) {
+                               if (!php_var_unserialize(&data, p, max, var_hash)) {
                                        zval_dtor(key);
                                        FREE_ZVAL(key);
                                        zval_dtor(data);
@@ -558,6 +613,7 @@ int php_var_unserialize(pval **rval, const char **p, const char *max)
 PHP_FUNCTION(serialize)
 {
        pval **struc;
+       php_serialize_data_t var_hash;
 
        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &struc) == FAILURE) {
                WRONG_PARAM_COUNT;
@@ -565,7 +621,10 @@ PHP_FUNCTION(serialize)
        return_value->type = IS_STRING;
        return_value->value.str.val = NULL;
        return_value->value.str.len = 0;
-       php_var_serialize(return_value, struc);
+
+       PHP_VAR_SERIALIZE_INIT(var_hash);
+       php_var_serialize(return_value, struc, &var_hash);
+       PHP_VAR_SERIALIZE_DESTROY(var_hash);
 }
 
 /* }}} */
@@ -576,6 +635,7 @@ PHP_FUNCTION(serialize)
 PHP_FUNCTION(unserialize)
 {
        pval **buf;
+       php_serialize_data_t var_hash;
        
        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &buf) == FAILURE) {
                WRONG_PARAM_COUNT;
@@ -588,11 +648,14 @@ PHP_FUNCTION(unserialize)
                        RETURN_FALSE;
                }
 
-               if (!php_var_unserialize(&return_value, &p, p + (*buf)->value.str.len)) {
+               PHP_VAR_UNSERIALIZE_INIT(var_hash);
+               if (!php_var_unserialize(&return_value, &p, p + (*buf)->value.str.len,  &var_hash)) {
+                       PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
                        zval_dtor(return_value);
                        php_error(E_NOTICE, "unserialize() failed at offset %d of %d bytes",p-(*buf)->value.str.val,(*buf)->value.str.len);
                        RETURN_FALSE;
                }
+               PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
        } else {
                php_error(E_NOTICE, "argument passed to unserialize() is not an string");
                RETURN_FALSE;
index b31a53d89924aabd9bbf6b3cfc93f40ac4fa19fa..6986a29295923a1d3262f3355103806b447accad 100644 (file)
@@ -233,7 +233,7 @@ PHP_FUNCTION(shm_put_var)
        shm_var.type=IS_STRING;
        shm_var.value.str.len=0;
        shm_var.value.str.val=0;
-       php_var_serialize(&shm_var,arg_var);
+       php_var_serialize(&shm_var,arg_var,NULL);
        /* 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);