Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:1015 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 56287 invoked from network); 23 Apr 2003 12:43:14 -0000 Received: from unknown (HELO alanathome.ossc.com.hk) (202.81.246.113) by pb1.pair.com with SMTP; 23 Apr 2003 12:43:14 -0000 Received: from devel ([192.168.0.40] helo=alan ident=mail) by alanathome.ossc.com.hk with esmtp (Exim 3.36 #1 (Debian)) id 198Jai-0000nf-00 for ; Wed, 23 Apr 2003 20:43:12 +0800 Received: from alan ([127.0.0.1] helo=akbkhome.com ident=alan) by alan with esmtp (Exim 3.36 #1 (Debian)) id 198JeW-0005zY-00 for ; Wed, 23 Apr 2003 20:47:08 +0800 Message-ID: <3EA68B4B.10209@akbkhome.com> Date: Wed, 23 Apr 2003 20:47:07 +0800 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3b) Gecko/20030210 X-Accept-Language: en-us, en MIME-Version: 1.0 To: internals@lists.php.net Content-Type: multipart/mixed; boundary="------------030101000300010805070703" Subject: wddx class mapping and pretty print From: alan@akbkhome.com (Alan Knowles) --------------030101000300010805070703 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit On one of those - xml is too difficult stints, I started thinking about using wddx as a generic storage system - perhaps thinking about things like MDB's data structure and the ability to load data.. I'm still thinking that it would be nice for wddx_deserialize to accept a stream - hence allowing the processing of huge xml files with minimal memory penalty.. This patch does 2 things. a) a deserialize class mapping - so you can map stored classes into different instantation classes. (usefull when you dont have the original - or just want to map it to something else. - eg use the data with an extended class. class tests_wddxtest { var $somearray = array(1,2,3); var $someassoc = array('dog'=>'cat','mouse'=>'cat'); var $child; function test() { foreach($this->somearray as $i) { $this->child[] = new tests_wddxtest; } } } $x = new tests_wddxtest; $x->test(); class silly { function __wakeup() { // echo "Construct silly"; print_r($this); $this = null; } } $xx = wddx_serialize_value($x, "Testing X"); wddx_map_class(array('gtk_classviewer_tests_wddxtest'=> 'silly')); $yy = wddx_deserialize($xx); var_dump($yy); in this example the wakup call can be used to commit to a database and free the memory :) - useful... b) pretty printing of the xml so that it could be hand edited if need.. - or just semi-human readable.. wddx_set_indent(2); $xx = wddx_serialize_value($x, "Testing X"); echo $xx; Comments Anyone..??? Regards Alan -- Can you help out? Need Consulting Services or Know of a Job? http://www.akbkhome.com -- Can you help out? Need Consulting Services or Know of a Job? http://www.akbkhome.com --------------030101000300010805070703 Content-Type: text/plain; name="wddx_classmap_and_pretty.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="wddx_classmap_and_pretty.diff" ? wddx_classmap_and_pretty.diff Index: php_wddx.h =================================================================== RCS file: /repository/php4/ext/wddx/php_wddx.h,v retrieving revision 1.13.2.1 diff -u -r1.13.2.1 php_wddx.h --- php_wddx.h 31 Dec 2002 16:35:42 -0000 1.13.2.1 +++ php_wddx.h 23 Apr 2003 12:30:18 -0000 @@ -34,6 +34,23 @@ PHP_FUNCTION(wddx_packet_end); PHP_FUNCTION(wddx_add_vars); PHP_FUNCTION(wddx_deserialize); +PHP_FUNCTION(wddx_map_class); +PHP_FUNCTION(wddx_set_indent); + +PHP_RINIT_FUNCTION(wddx); +PHP_RSHUTDOWN_FUNCTION(wddx); + +ZEND_BEGIN_MODULE_GLOBALS(wddx) + HashTable *wddx_class_map; + int indent; + int current_indent; +ZEND_END_MODULE_GLOBALS(wddx) + +#ifdef ZTS +#define WDDX_G(v) TSRMG(wddx_globals_id, zend_wddx_globals *, v) +#else +#define WDDX_G(v) (wddx_globals.v) +#endif #else Index: wddx.c =================================================================== RCS file: /repository/php4/ext/wddx/wddx.c,v retrieving revision 1.96.2.3 diff -u -r1.96.2.3 wddx.c --- wddx.c 4 Jan 2003 19:51:46 -0000 1.96.2.3 +++ wddx.c 23 Apr 2003 12:30:19 -0000 @@ -64,6 +64,7 @@ } else \ ent.varname = NULL; \ + static int le_wddx; typedef struct { @@ -92,6 +93,9 @@ static void php_wddx_process_data(void *user_data, const char *s, int len); + +ZEND_DECLARE_MODULE_GLOBALS(wddx) + /* {{{ wddx_functions[] */ function_entry wddx_functions[] = { @@ -101,6 +105,8 @@ PHP_FE(wddx_packet_end, NULL) PHP_FE(wddx_add_vars, NULL) PHP_FE(wddx_deserialize, NULL) + PHP_FE(wddx_map_class, NULL) + PHP_FE(wddx_set_indent, NULL) {NULL, NULL, NULL} }; /* }}} */ @@ -122,14 +128,36 @@ wddx_functions, PHP_MINIT(wddx), NULL, - NULL, - NULL, + PHP_RINIT(wddx), + PHP_RSHUTDOWN(wddx), PHP_MINFO(wddx), - NO_VERSION_YET, + NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; /* }}} */ + + +PHP_RINIT_FUNCTION(wddx) +{ + WDDX_G(wddx_class_map) =NULL; + WDDX_G(indent) =0; + return SUCCESS; +} + + + +PHP_RSHUTDOWN_FUNCTION(wddx) +{ + if (WDDX_G(wddx_class_map)) { + zend_hash_destroy(WDDX_G(wddx_class_map)); + } + return SUCCESS; +} + + + + /* {{{ wddx_stack_init */ static int wddx_stack_init(wddx_stack *stack) @@ -330,19 +358,63 @@ } /* }}} */ + + +void php_wddx_add_start(wddx_packet *packet,int add) +{ + char *s; + int l; + if (!WDDX_G(indent)) { + return; + } + if (add < 0) { + WDDX_G(current_indent) += add; + } + php_wddx_add_chunk_static(packet,"\n"); + l = WDDX_G(current_indent) * WDDX_G(indent); + + if (l) { + s = emalloc(l); + memset(s,32,l); + + php_wddx_add_chunk_ex(packet,s,l); + } + if (add > 0) { + WDDX_G(current_indent) += add; + } +} +void php_wddx_add_end() +{ + if (!WDDX_G(indent)) { + return; + } + WDDX_G(current_indent)--; +} + /* {{{ php_wddx_packet_start */ void php_wddx_packet_start(wddx_packet *packet, char *comment, int comment_len) { + WDDX_G(current_indent) = 0; + php_wddx_add_start(packet,1); php_wddx_add_chunk_static(packet, WDDX_PACKET_S); if (comment) { + php_wddx_add_start(packet,1); php_wddx_add_chunk_static(packet, WDDX_HEADER_S); + + php_wddx_add_start(packet,0); php_wddx_add_chunk_static(packet, WDDX_COMMENT_S); php_wddx_add_chunk_ex(packet, comment, comment_len); php_wddx_add_chunk_static(packet, WDDX_COMMENT_E); + + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_HEADER_E); - } else + + } else { + php_wddx_add_start(packet,0); php_wddx_add_chunk_static(packet, WDDX_HEADER); + } + php_wddx_add_start(packet,1); php_wddx_add_chunk_static(packet, WDDX_DATA_S); } /* }}} */ @@ -351,8 +423,11 @@ */ void php_wddx_packet_end(wddx_packet *packet) { + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_DATA_E); + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_PACKET_E); + } /* }}} */ @@ -371,7 +446,7 @@ *vend, control_buf[WDDX_BUF_LEN]; int l; - + php_wddx_add_start(packet,0); php_wddx_add_chunk_static(packet, WDDX_STRING_S); if (Z_STRLEN_P(var) > 0) { @@ -410,7 +485,7 @@ FLUSH_BUF(); efree(buf); } - + php_wddx_add_chunk_static(packet, WDDX_STRING_E); } /* }}} */ @@ -447,6 +522,7 @@ */ static void php_wddx_serialize_unset(wddx_packet *packet) { + php_wddx_add_start(packet,0); php_wddx_add_chunk_static(packet, WDDX_NULL); } /* }}} */ @@ -475,20 +551,26 @@ PHP_CLASS_ATTRIBUTES; PHP_SET_CLASS_ATTRIBUTES(obj); - + php_wddx_add_start(packet,1); php_wddx_add_chunk_static(packet, WDDX_STRUCT_S); + + php_wddx_add_start(packet,1); sprintf(tmp_buf, WDDX_VAR_S, PHP_CLASS_NAME_VAR); php_wddx_add_chunk(packet, tmp_buf); + + php_wddx_add_start(packet,0); php_wddx_add_chunk_static(packet, WDDX_STRING_S); php_wddx_add_chunk_ex(packet, class_name, name_len); php_wddx_add_chunk_static(packet, WDDX_STRING_E); + + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_VAR_E); PHP_CLEANUP_CLASS_ATTRIBUTES(); for (zend_hash_internal_pointer_reset(HASH_OF(retval)); - zend_hash_get_current_data(HASH_OF(retval), (void **)&varname) == SUCCESS; - zend_hash_move_forward(HASH_OF(retval))) { + zend_hash_get_current_data(HASH_OF(retval), (void **)&varname) == SUCCESS; + zend_hash_move_forward(HASH_OF(retval))) { if (Z_TYPE_PP(varname) != IS_STRING) { php_error(E_NOTICE, "__sleep should return an array only containing the names of instance-variables to serialize."); continue; @@ -498,7 +580,7 @@ php_wddx_serialize_var(packet, *ent, Z_STRVAL_PP(varname), Z_STRLEN_PP(varname) TSRMLS_CC); } } - + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_STRUCT_E); } } else { @@ -507,13 +589,19 @@ PHP_CLASS_ATTRIBUTES; PHP_SET_CLASS_ATTRIBUTES(obj); - + + php_wddx_add_start(packet,1); php_wddx_add_chunk_static(packet, WDDX_STRUCT_S); + + php_wddx_add_start(packet,1); sprintf(tmp_buf, WDDX_VAR_S, PHP_CLASS_NAME_VAR); php_wddx_add_chunk(packet, tmp_buf); + + php_wddx_add_start(packet,0); php_wddx_add_chunk_static(packet, WDDX_STRING_S); php_wddx_add_chunk_ex(packet, class_name, name_len); php_wddx_add_chunk_static(packet, WDDX_STRING_E); + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_VAR_E); PHP_CLEANUP_CLASS_ATTRIBUTES(); @@ -531,6 +619,7 @@ php_wddx_serialize_var(packet, *ent, tmp_buf, key_len TSRMLS_CC); } } + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_STRUCT_E); } @@ -580,9 +669,11 @@ } if (is_struct) { + php_wddx_add_start(packet,1); php_wddx_add_chunk_static(packet, WDDX_STRUCT_S); } else { sprintf(tmp_buf, WDDX_ARRAY_S, zend_hash_num_elements(target_hash)); + php_wddx_add_start(packet,1); php_wddx_add_chunk(packet, tmp_buf); } @@ -601,13 +692,17 @@ key_len = sprintf(tmp_buf, "%ld", idx); php_wddx_serialize_var(packet, *ent, tmp_buf, key_len TSRMLS_CC); } - } else + } else { + php_wddx_add_start(packet,0); php_wddx_serialize_var(packet, *ent, NULL, 0 TSRMLS_CC); + } } if (is_struct) { + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_STRUCT_E); } else { + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_ARRAY_E); } } @@ -620,10 +715,11 @@ char tmp_buf[WDDX_BUF_LEN]; char *name_esc; int name_esc_len; - + if (name) { name_esc = php_escape_html_entities(name, name_len, &name_esc_len, 0, ENT_QUOTES, NULL TSRMLS_CC); sprintf(tmp_buf, WDDX_VAR_S, name_esc); + php_wddx_add_start(packet,1); php_wddx_add_chunk(packet, tmp_buf); efree(name_esc); } @@ -656,6 +752,7 @@ } if (name) { + php_wddx_add_start(packet,-1); php_wddx_add_chunk_static(packet, WDDX_VAR_E); } } @@ -936,12 +1033,27 @@ if (!strcmp(ent1->varname, PHP_CLASS_NAME_VAR) && Z_TYPE_P(ent1->data) == IS_STRING && Z_STRLEN_P(ent1->data)) { zend_bool incomplete_class = 0; + zval **mapped_class = NULL; zend_str_tolower(Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data)); - if (zend_hash_find(EG(class_table), Z_STRVAL_P(ent1->data), + + + if (WDDX_G(wddx_class_map) && zend_hash_find(WDDX_G(wddx_class_map), Z_STRVAL_P(ent1->data), + Z_STRLEN_P(ent1->data)+1, (void **) &mapped_class)!=FAILURE) { + + if (zend_hash_find(EG(class_table), Z_STRVAL_PP(mapped_class), + Z_STRLEN_PP(mapped_class)+1, (void **) &ce)==FAILURE) { + incomplete_class = 1; + ce = PHP_IC_ENTRY; + } + + } else { + + if (zend_hash_find(EG(class_table), Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data)+1, (void **) &ce)==FAILURE) { - incomplete_class = 1; - ce = PHP_IC_ENTRY; + incomplete_class = 1; + ce = PHP_IC_ENTRY; + } } /* Initialize target object */ @@ -957,7 +1069,7 @@ if (incomplete_class) { php_store_class_name(obj, Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data) TSRMLS_CC); - } + } /* Clean up old array entry */ zval_ptr_dtor(&ent2->data); @@ -1298,6 +1410,50 @@ php_wddx_deserialize_ex(packet, packet_len, return_value); } /* }}} */ + + + +/* {{{ proto boolean wddx_deserialize([array original_class=>new_class]) + Maps a stored class to a different class, empty clears the mapping */ +PHP_FUNCTION(wddx_map_class) +{ + + + zval *array = NULL; + zval *tmp; + HashTable *from; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a",&array) == FAILURE) { + RETURN_FALSE; + } + if (WDDX_G(wddx_class_map)) { + zend_hash_clean(WDDX_G(wddx_class_map)); + } else { + ALLOC_HASHTABLE(WDDX_G(wddx_class_map)); + zend_hash_init(WDDX_G(wddx_class_map), 0, NULL, ZVAL_PTR_DTOR, 0); + } + if (!array) { + RETURN_TRUE; + } + from = HASH_OF(array); + zend_hash_copy(WDDX_G(wddx_class_map),from , (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto boolean wddx_set_indent(int spaces) + makes the output wddx data have indents (default is 0 - no indentation) */ +PHP_FUNCTION(wddx_set_indent) +{ + int indent; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",&indent) == FAILURE) { + RETURN_FALSE; + } + WDDX_G(indent) = indent; + RETURN_TRUE; +} + + #endif /* HAVE_LIBEXPAT */ --------------030101000300010805070703--