diff options
author | Stanislav Malyshev <stas@php.net> | 2005-02-23 11:17:52 +0000 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2005-02-23 11:17:52 +0000 |
commit | db3fdce304a9ba026f355fb3d03e9d2eb45cda5d (patch) | |
tree | 5d305df1568513c07c66296bffce1c13fc9358c3 | |
parent | 5b98a092195a7977fa3f4ab0d6d8918654d50ff9 (diff) | |
download | php-git-db3fdce304a9ba026f355fb3d03e9d2eb45cda5d.tar.gz |
Custom object serializer infrastructure - PHP implementation
# The detailed announce on the list will follow
-rw-r--r-- | ext/standard/var.c | 25 | ||||
-rw-r--r-- | ext/standard/var_unserializer.c | 228 | ||||
-rw-r--r-- | ext/standard/var_unserializer.re | 46 |
3 files changed, 165 insertions, 134 deletions
diff --git a/ext/standard/var.c b/ext/standard/var.c index c07696aabe..21605d21b9 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -671,6 +671,31 @@ static void php_var_serialize_intern(smart_str *buf, zval **struc, HashTable *va zval fname; int res; + if(Z_OBJCE_PP(struc)->serialize != NULL) { + /* has custom handler */ + unsigned char *serialized_data = NULL; + zend_uint serialized_length; + + if(Z_OBJCE_PP(struc)->serialize(*struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash TSRMLS_CC) == SUCCESS) { + smart_str_appendl(buf, "C:", 2); + smart_str_append_long(buf, Z_OBJCE_PP(struc)->name_length); + smart_str_appendl(buf, ":\"", 2); + smart_str_appendl(buf, Z_OBJCE_PP(struc)->name, Z_OBJCE_PP(struc)->name_length); + smart_str_appendl(buf, "\":", 2); + + smart_str_append_long(buf, serialized_length); + smart_str_appendl(buf, ":{", 2); + smart_str_appendl(buf, serialized_data, serialized_length); + smart_str_appendc(buf, '}'); + } else { + smart_str_appendl(buf, "N;", 2); + } + if(serialized_data) { + efree(serialized_data); + } + return; + } + if(Z_OBJCE_PP(struc) != PHP_IC_ENTRY) { INIT_PZVAL(&fname); ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0); diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index a89db23f4a..0c07a60700 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,5 +1,5 @@ -/* Generated by re2c 0.9.4 on Mon Feb 14 21:57:21 2005 */ -#line 1 "/usr/src/php-cvs/ext/standard/var_unserializer.re" +/* Generated by re2c 0.5 on Tue Feb 22 15:14:56 2005 */ +#line 1 "/php5/ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ | PHP Version 5 | @@ -147,7 +147,7 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) #define YYMARKER marker -#line 154 "/usr/src/php-cvs/ext/standard/var_unserializer.re" +#line 155 @@ -277,6 +277,33 @@ static inline int finish_nested_data(UNSERIALIZE_PARAMETER) return 0; } +static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce) +{ + int datalen; + + if(ce->unserialize == NULL) { + zend_error(E_WARNING, "Class %s has no unserializer", ce->name); + return 0; + } + + datalen = parse_iv2((*p) + 2, p); + + (*p) += 2; + + if((*p) + datalen >= max) { + zend_error(E_WARNING, "Unsifficient data for unserializing - %d required, %d present", datalen, max - (*p)); + return 0; + } + + if(ce->unserialize(rval, *p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) { + return 0; + } + + (*p) += datalen; + + return finish_nested_data(UNSERIALIZE_PASSTHRU); +} + static inline int object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) { int elements; @@ -326,8 +353,6 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) - -#line 7 "<stdout>" { YYCTYPE yych; unsigned int yyaccept; @@ -370,29 +395,30 @@ yy1: ++YYCURSOR; yy0: if((YYLIMIT - YYCURSOR) < 7) YYFILL(7); yych = *YYCURSOR; - if(yych <= 'd'){ - if(yych <= 'R'){ - if(yych <= 'N'){ - if(yych <= 'M') goto yy16; - goto yy6; + if(yych <= 'c'){ + if(yych <= 'O'){ + if(yych <= 'C'){ + if(yych <= 'B') goto yy16; + goto yy13; } else { - if(yych <= 'O') goto yy13; - if(yych <= 'Q') goto yy16; - goto yy3; + if(yych <= 'M') goto yy16; + if(yych <= 'N') goto yy6; + goto yy13; } } else { - if(yych <= 'a'){ - if(yych <= '`') goto yy16; - goto yy11; + if(yych <= '`'){ + if(yych == 'R') goto yy3; + goto yy16; } else { + if(yych <= 'a') goto yy11; if(yych <= 'b') goto yy7; - if(yych <= 'c') goto yy16; - goto yy9; + goto yy16; } } } else { if(yych <= 'q'){ if(yych <= 'i'){ + if(yych <= 'd') goto yy9; if(yych <= 'h') goto yy16; goto yy8; } else { @@ -406,8 +432,7 @@ yy0: goto yy16; } else { if(yych <= '}') goto yy14; - if(yych <= 0xBF) goto yy16; - goto yy2; + if(yych <= '\277') goto yy16; } } } @@ -418,11 +443,9 @@ yy2: YYCURSOR = YYMARKER; yy3: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if(yych == ':') goto yy87; - goto yy4; yy4: -#line 581 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ return 0; } -#line 102 "<stdout>" +#line 620 + { return 0; } yy5: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if(yych == ':') goto yy81; @@ -458,51 +481,49 @@ yy13: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if(yych == ':') goto yy17; goto yy4; -yy14: ++YYCURSOR; - goto yy15; +yy14: yych = *++YYCURSOR; yy15: -#line 575 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 614 + { /* this is the case where we have less data than planned */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 147 "<stdout>" yy16: yych = *++YYCURSOR; goto yy4; yy17: yych = *++YYCURSOR; if(yybm[0+yych] & 128) goto yy19; if(yych != '+') goto yy2; - goto yy18; yy18: yych = *++YYCURSOR; if(yybm[0+yych] & 128) goto yy19; goto yy2; yy19: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy20; yy20: if(yybm[0+yych] & 128) goto yy19; if(yych != ':') goto yy2; - goto yy21; yy21: yych = *++YYCURSOR; if(yych != '"') goto yy2; - goto yy22; -yy22: ++YYCURSOR; - goto yy23; +yy22: yych = *++YYCURSOR; yy23: -#line 475 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 503 + { size_t len, len2, len3, maxlen; int elements; char *class_name; zend_class_entry *ce; zend_class_entry **pce; int incomplete_class = 0; - + int custom_object = 0; +/* */ zval *user_func; zval *retval_ptr; zval **args[1]; zval *arg_func_name; + + if(*start == 'C') { + custom_object = 1; + } INIT_PZVAL(*rval); len2 = len = parse_uiv(start + 2); @@ -579,8 +600,14 @@ yy23: zval_ptr_dtor(&arg_func_name); break; } while (1); - + *p = YYCURSOR; + + if(custom_object) { + efree(class_name); + return object_custom(UNSERIALIZE_PASSTHRU, ce); + } + elements = object_common1(UNSERIALIZE_PASSTHRU, ce); if (incomplete_class) { @@ -590,11 +617,9 @@ yy23: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 271 "<stdout>" yy24: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; - goto yy25; } else { if(yych <= '-') goto yy25; if(yych <= '/') goto yy2; @@ -604,30 +629,24 @@ yy24: yych = *++YYCURSOR; yy25: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy26; yy26: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy27; yy27: if(yych <= '/') goto yy2; if(yych <= '9') goto yy26; if(yych >= ';') goto yy2; - goto yy28; yy28: yych = *++YYCURSOR; if(yych != '"') goto yy2; - goto yy29; -yy29: ++YYCURSOR; - goto yy30; +yy29: yych = *++YYCURSOR; yy30: -#line 467 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 495 + { INIT_PZVAL(*rval); return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 309 "<stdout>" yy31: yych = *++YYCURSOR; if(yych == '+') goto yy32; if(yych <= '/') goto yy2; @@ -636,23 +655,18 @@ yy31: yych = *++YYCURSOR; yy32: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy33; yy33: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy34; yy34: if(yych <= '/') goto yy2; if(yych <= '9') goto yy33; if(yych >= ';') goto yy2; - goto yy35; yy35: yych = *++YYCURSOR; if(yych != '{') goto yy2; - goto yy36; -yy36: ++YYCURSOR; - goto yy37; +yy36: yych = *++YYCURSOR; yy37: -#line 449 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 477 + { int elements = parse_iv(start + 2); *p = YYCURSOR; @@ -669,7 +683,6 @@ yy37: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 352 "<stdout>" yy38: yych = *++YYCURSOR; if(yych == '+') goto yy39; if(yych <= '/') goto yy2; @@ -678,23 +691,18 @@ yy38: yych = *++YYCURSOR; yy39: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy40; yy40: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy41; yy41: if(yych <= '/') goto yy2; if(yych <= '9') goto yy40; if(yych >= ';') goto yy2; - goto yy42; yy42: yych = *++YYCURSOR; if(yych != '"') goto yy2; - goto yy43; -yy43: ++YYCURSOR; - goto yy44; +yy43: yych = *++YYCURSOR; yy44: -#line 421 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 449 + { size_t len, maxlen; char *str; @@ -721,7 +729,6 @@ yy44: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 405 "<stdout>" yy45: yych = *++YYCURSOR; if(yych <= '/'){ if(yych <= ','){ @@ -739,7 +746,6 @@ yy45: yych = *++YYCURSOR; goto yy48; } else { if(yych != 'N') goto yy2; - goto yy46; } } yy46: yych = *++YYCURSOR; @@ -752,7 +758,6 @@ yy47: yych = *++YYCURSOR; } else { if(yych <= '9') goto yy50; if(yych != 'I') goto yy2; - goto yy48; } yy48: yych = *++YYCURSOR; if(yych == 'N') goto yy64; @@ -761,11 +766,9 @@ yy49: yych = *++YYCURSOR; if(yych == '.') goto yy52; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy50; yy50: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy51; yy51: if(yych <= ':'){ if(yych <= '.'){ if(yych <= '-') goto yy2; @@ -788,16 +791,13 @@ yy51: if(yych <= ':'){ yy52: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy53; yy53: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy54; yy54: if(yych <= ';'){ if(yych <= '/') goto yy2; if(yych <= '9') goto yy53; if(yych <= ':') goto yy2; - goto yy55; } else { if(yych <= 'E'){ if(yych <= 'D') goto yy2; @@ -807,21 +807,18 @@ yy54: if(yych <= ';'){ goto yy2; } } -yy55: ++YYCURSOR; - goto yy56; +yy55: yych = *++YYCURSOR; yy56: -#line 414 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 442 + { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_DOUBLE(*rval, zend_strtod(start + 2, NULL)); return 1; } -#line 503 "<stdout>" yy57: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; - goto yy58; } else { if(yych <= '-') goto yy58; if(yych <= '/') goto yy2; @@ -836,12 +833,10 @@ yy58: yych = *++YYCURSOR; if(yych <= '-') goto yy61; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy59; } yy59: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy60; yy60: if(yych <= '/') goto yy2; if(yych <= '9') goto yy59; if(yych == ';') goto yy55; @@ -853,7 +848,6 @@ yy61: yych = *++YYCURSOR; yy62: ++YYCURSOR; if((YYLIMIT - YYCURSOR) < 4) YYFILL(4); yych = *YYCURSOR; - goto yy63; yy63: if(yych <= ';'){ if(yych <= '/') goto yy2; if(yych <= '9') goto yy62; @@ -870,15 +864,12 @@ yy63: if(yych <= ';'){ } yy64: yych = *++YYCURSOR; if(yych != 'F') goto yy2; - goto yy65; yy65: yych = *++YYCURSOR; if(yych != ';') goto yy2; - goto yy66; -yy66: ++YYCURSOR; - goto yy67; +yy66: yych = *++YYCURSOR; yy67: -#line 399 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 427 + { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -892,14 +883,12 @@ yy67: return 1; } -#line 580 "<stdout>" yy68: yych = *++YYCURSOR; if(yych == 'N') goto yy65; goto yy2; yy69: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; - goto yy70; } else { if(yych <= '-') goto yy70; if(yych <= '/') goto yy2; @@ -909,59 +898,47 @@ yy69: yych = *++YYCURSOR; yy70: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy71; yy71: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy72; yy72: if(yych <= '/') goto yy2; if(yych <= '9') goto yy71; if(yych != ';') goto yy2; - goto yy73; -yy73: ++YYCURSOR; - goto yy74; +yy73: yych = *++YYCURSOR; yy74: -#line 392 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 420 + { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 617 "<stdout>" yy75: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= '2') goto yy2; - goto yy76; yy76: yych = *++YYCURSOR; if(yych != ';') goto yy2; - goto yy77; -yy77: ++YYCURSOR; - goto yy78; +yy77: yych = *++YYCURSOR; yy78: -#line 385 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 413 + { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 635 "<stdout>" -yy79: ++YYCURSOR; - goto yy80; +yy79: yych = *++YYCURSOR; yy80: -#line 378 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 406 + { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 646 "<stdout>" yy81: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; - goto yy82; } else { if(yych <= '-') goto yy82; if(yych <= '/') goto yy2; @@ -971,20 +948,16 @@ yy81: yych = *++YYCURSOR; yy82: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy83; yy83: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy84; yy84: if(yych <= '/') goto yy2; if(yych <= '9') goto yy83; if(yych != ';') goto yy2; - goto yy85; -yy85: ++YYCURSOR; - goto yy86; +yy85: yych = *++YYCURSOR; yy86: -#line 355 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 383 + { int id; *p = YYCURSOR; @@ -1006,11 +979,9 @@ yy86: return 1; } -#line 696 "<stdout>" yy87: yych = *++YYCURSOR; if(yych <= ','){ if(yych != '+') goto yy2; - goto yy88; } else { if(yych <= '-') goto yy88; if(yych <= '/') goto yy2; @@ -1020,20 +991,16 @@ yy87: yych = *++YYCURSOR; yy88: yych = *++YYCURSOR; if(yych <= '/') goto yy2; if(yych >= ':') goto yy2; - goto yy89; yy89: ++YYCURSOR; if(YYLIMIT == YYCURSOR) YYFILL(1); yych = *YYCURSOR; - goto yy90; yy90: if(yych <= '/') goto yy2; if(yych <= '9') goto yy89; if(yych != ';') goto yy2; - goto yy91; -yy91: ++YYCURSOR; - goto yy92; +yy91: yych = *++YYCURSOR; yy92: -#line 334 "/usr/src/php-cvs/ext/standard/var_unserializer.re" -{ +#line 362 + { int id; *p = YYCURSOR; @@ -1053,9 +1020,8 @@ yy92: return 1; } -#line 744 "<stdout>" } -#line 583 "/usr/src/php-cvs/ext/standard/var_unserializer.re" +#line 622 return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index bc2a477df3..d175731786 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -151,6 +151,7 @@ iv = [+-]? [0-9]+; nv = [+-]? ([0-9]* "." [0-9]+|[0-9]+ "." [0-9]*); nvexp = (iv | nv) [eE] [+-]? iv; any = [\000-\277]; +object = [OC]; */ @@ -280,6 +281,33 @@ static inline int finish_nested_data(UNSERIALIZE_PARAMETER) return 0; } +static inline int object_custom(UNSERIALIZE_PARAMETER, zend_class_entry *ce) +{ + int datalen; + + if(ce->unserialize == NULL) { + zend_error(E_WARNING, "Class %s has no unserializer", ce->name); + return 0; + } + + datalen = parse_iv2((*p) + 2, p); + + (*p) += 2; + + if((*p) + datalen >= max) { + zend_error(E_WARNING, "Unsifficient data for unserializing - %d required, %d present", datalen, max - (*p)); + return 0; + } + + if(ce->unserialize(rval, *p, datalen, (zend_unserialize_data *)var_hash TSRMLS_CC) != SUCCESS) { + return 0; + } + + (*p) += datalen; + + return finish_nested_data(UNSERIALIZE_PASSTHRU); +} + static inline int object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) { int elements; @@ -472,18 +500,24 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -"O:" uiv ":" ["] { +object ":" uiv ":" ["] { size_t len, len2, len3, maxlen; int elements; char *class_name; zend_class_entry *ce; zend_class_entry **pce; int incomplete_class = 0; - + + int custom_object = 0; + zval *user_func; zval *retval_ptr; zval **args[1]; zval *arg_func_name; + + if(*start == 'C') { + custom_object = 1; + } INIT_PZVAL(*rval); len2 = len = parse_uiv(start + 2); @@ -560,8 +594,14 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) zval_ptr_dtor(&arg_func_name); break; } while (1); - + *p = YYCURSOR; + + if(custom_object) { + efree(class_name); + return object_custom(UNSERIALIZE_PASSTHRU, ce); + } + elements = object_common1(UNSERIALIZE_PASSTHRU, ce); if (incomplete_class) { |