@@ -1070,6 +1070,247 @@ PHP_METHOD(SplPriorityQueue, __debugInfo)
10701070 RETURN_ARR (spl_heap_object_get_debug_info (spl_ce_SplPriorityQueue , Z_OBJ_P (ZEND_THIS )));
10711071} /* }}} */
10721072
1073+ static void spl_heap_serialize_internal_state (zval * return_value , spl_heap_object * intern , bool is_pqueue )
1074+ {
1075+ zval heap_elements ;
1076+ int heap_count = intern -> heap -> count ;
1077+
1078+ array_init (return_value );
1079+ add_assoc_long (return_value , "flags" , intern -> flags );
1080+
1081+ array_init_size (& heap_elements , heap_count );
1082+
1083+ if (heap_count == 0 ) {
1084+ add_assoc_zval (return_value , "heap_elements" , & heap_elements );
1085+ return ;
1086+ }
1087+
1088+ for (int heap_idx = 0 ; heap_idx < heap_count ; ++ heap_idx ) {
1089+ if (is_pqueue ) {
1090+ spl_pqueue_elem * elem = spl_heap_elem (intern -> heap , heap_idx );
1091+ zval entry ;
1092+ array_init (& entry );
1093+ add_assoc_zval_ex (& entry , "data" , strlen ("data" ), & elem -> data );
1094+ Z_TRY_ADDREF (elem -> data );
1095+ add_assoc_zval_ex (& entry , "priority" , strlen ("priority" ), & elem -> priority );
1096+ Z_TRY_ADDREF (elem -> priority );
1097+ zend_hash_next_index_insert (Z_ARRVAL (heap_elements ), & entry );
1098+ } else {
1099+ zval * elem = spl_heap_elem (intern -> heap , heap_idx );
1100+ zend_hash_next_index_insert (Z_ARRVAL (heap_elements ), elem );
1101+ Z_TRY_ADDREF_P (elem );
1102+ }
1103+ }
1104+
1105+ add_assoc_zval (return_value , "heap_elements" , & heap_elements );
1106+ }
1107+
1108+ static zend_result spl_heap_unserialize_internal_state (HashTable * state_ht , spl_heap_object * intern , zval * this_ptr , bool is_pqueue )
1109+ {
1110+ zval * flags_val = zend_hash_str_find (state_ht , "flags" , strlen ("flags" ));
1111+ if (!flags_val || Z_TYPE_P (flags_val ) != IS_LONG ) {
1112+ return FAILURE ;
1113+ }
1114+
1115+ zend_long flags_value = Z_LVAL_P (flags_val );
1116+
1117+ if (is_pqueue ) {
1118+ flags_value &= SPL_PQUEUE_EXTR_MASK ;
1119+ if (!flags_value ) {
1120+ return FAILURE ;
1121+ }
1122+ } else if (flags_value != 0 ) { /* Regular heaps should not have user-visible flags */
1123+ return FAILURE ;
1124+ }
1125+
1126+ intern -> flags = (int ) flags_value ;
1127+
1128+ zval * heap_elements = zend_hash_str_find (state_ht , "heap_elements" , strlen ("heap_elements" ));
1129+ if (!heap_elements ) {
1130+ return FAILURE ;
1131+ }
1132+
1133+ if (Z_TYPE_P (heap_elements ) != IS_ARRAY ) {
1134+ return FAILURE ;
1135+ }
1136+
1137+ ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (heap_elements ), zval * val ) {
1138+ if (is_pqueue ) {
1139+ /* PriorityQueue elements are serialized as arrays with 'data' and 'priority' keys */
1140+ if (Z_TYPE_P (val ) != IS_ARRAY || zend_hash_num_elements (Z_ARRVAL_P (val )) != 2 ) {
1141+ return FAILURE ;
1142+ }
1143+
1144+ zval * data_val = zend_hash_str_find (Z_ARRVAL_P (val ), "data" , strlen ("data" ) );
1145+ zval * priority_val = zend_hash_str_find (Z_ARRVAL_P (val ), "priority" , strlen ("priority" ));
1146+
1147+ if (!data_val || !priority_val ) {
1148+ return FAILURE ;
1149+ }
1150+
1151+ spl_pqueue_elem elem ;
1152+ ZVAL_COPY (& elem .data , data_val );
1153+ ZVAL_COPY (& elem .priority , priority_val );
1154+ spl_ptr_heap_insert (intern -> heap , & elem , this_ptr );
1155+ if (EG (exception )) {
1156+ return FAILURE ;
1157+ }
1158+ } else {
1159+ Z_TRY_ADDREF_P (val );
1160+ spl_ptr_heap_insert (intern -> heap , val , this_ptr );
1161+ if (EG (exception )) {
1162+ return FAILURE ;
1163+ }
1164+ }
1165+ } ZEND_HASH_FOREACH_END ();
1166+
1167+ return SUCCESS ;
1168+ }
1169+
1170+ PHP_METHOD (SplPriorityQueue , __serialize )
1171+ {
1172+ spl_heap_object * intern = Z_SPLHEAP_P (ZEND_THIS );
1173+ zval props , state ;
1174+
1175+ ZEND_PARSE_PARAMETERS_NONE ();
1176+
1177+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
1178+ RETURN_THROWS ();
1179+ }
1180+
1181+ if (intern -> heap -> flags & SPL_HEAP_WRITE_LOCKED ) {
1182+ zend_throw_exception (spl_ce_RuntimeException , "Cannot serialize heap while it is being modified." , 0 );
1183+ RETURN_THROWS ();
1184+ }
1185+
1186+ array_init (return_value );
1187+
1188+ ZVAL_ARR (& props , zend_std_get_properties (& intern -> std ));
1189+ Z_TRY_ADDREF (props );
1190+ zend_hash_next_index_insert (Z_ARRVAL_P (return_value ), & props );
1191+
1192+ spl_heap_serialize_internal_state (& state , intern , true);
1193+ zend_hash_next_index_insert (Z_ARRVAL_P (return_value ), & state );
1194+ }
1195+
1196+ PHP_METHOD (SplPriorityQueue , __unserialize )
1197+ {
1198+ HashTable * data ;
1199+ spl_heap_object * intern = Z_SPLHEAP_P (ZEND_THIS );
1200+
1201+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
1202+ Z_PARAM_ARRAY_HT (data )
1203+ ZEND_PARSE_PARAMETERS_END ();
1204+
1205+ if (zend_hash_num_elements (data ) != 2 ) {
1206+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1207+ RETURN_THROWS ();
1208+ }
1209+
1210+ zval * props = zend_hash_index_find (data , 0 );
1211+ if (!props || Z_TYPE_P (props ) != IS_ARRAY ) {
1212+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1213+ RETURN_THROWS ();
1214+ }
1215+
1216+ object_properties_load (& intern -> std , Z_ARRVAL_P (props ));
1217+ if (EG (exception )) {
1218+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1219+ RETURN_THROWS ();
1220+ }
1221+
1222+ zval * state = zend_hash_index_find (data , 1 );
1223+ if (!state || Z_TYPE_P (state ) != IS_ARRAY ) {
1224+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1225+ RETURN_THROWS ();
1226+ }
1227+
1228+ if (spl_heap_unserialize_internal_state (Z_ARRVAL_P (state ), intern , ZEND_THIS , true) != SUCCESS ) {
1229+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1230+ RETURN_THROWS ();
1231+ }
1232+
1233+ if (EG (exception )) {
1234+ RETURN_THROWS ();
1235+ }
1236+
1237+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
1238+ RETURN_THROWS ();
1239+ }
1240+ }
1241+
1242+ PHP_METHOD (SplHeap , __serialize )
1243+ {
1244+ spl_heap_object * intern = Z_SPLHEAP_P (ZEND_THIS );
1245+ zval props , state ;
1246+
1247+ ZEND_PARSE_PARAMETERS_NONE ();
1248+
1249+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
1250+ RETURN_THROWS ();
1251+ }
1252+
1253+ if (intern -> heap -> flags & SPL_HEAP_WRITE_LOCKED ) {
1254+ zend_throw_exception (spl_ce_RuntimeException , "Cannot serialize heap while it is being modified." , 0 );
1255+ RETURN_THROWS ();
1256+ }
1257+
1258+ array_init (return_value );
1259+
1260+ ZVAL_ARR (& props , zend_std_get_properties (& intern -> std ));
1261+ Z_TRY_ADDREF (props );
1262+ zend_hash_next_index_insert (Z_ARRVAL_P (return_value ), & props );
1263+
1264+ spl_heap_serialize_internal_state (& state , intern , false);
1265+ zend_hash_next_index_insert (Z_ARRVAL_P (return_value ), & state );
1266+ }
1267+
1268+ PHP_METHOD (SplHeap , __unserialize )
1269+ {
1270+ HashTable * data ;
1271+ spl_heap_object * intern = Z_SPLHEAP_P (ZEND_THIS );
1272+
1273+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
1274+ Z_PARAM_ARRAY_HT (data )
1275+ ZEND_PARSE_PARAMETERS_END ();
1276+
1277+ if (zend_hash_num_elements (data ) != 2 ) {
1278+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1279+ RETURN_THROWS ();
1280+ }
1281+
1282+ zval * props = zend_hash_index_find (data , 0 );
1283+ if (!props || Z_TYPE_P (props ) != IS_ARRAY ) {
1284+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1285+ RETURN_THROWS ();
1286+ }
1287+
1288+ object_properties_load (& intern -> std , Z_ARRVAL_P (props ));
1289+ if (EG (exception )) {
1290+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1291+ RETURN_THROWS ();
1292+ }
1293+
1294+ zval * state = zend_hash_index_find (data , 1 );
1295+ if (!state || Z_TYPE_P (state ) != IS_ARRAY ) {
1296+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1297+ RETURN_THROWS ();
1298+ }
1299+
1300+ if (spl_heap_unserialize_internal_state (Z_ARRVAL_P (state ), intern , ZEND_THIS , false) != SUCCESS ) {
1301+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (intern -> std .ce -> name ));
1302+ RETURN_THROWS ();
1303+ }
1304+
1305+ if (EG (exception )) {
1306+ RETURN_THROWS ();
1307+ }
1308+
1309+ if (UNEXPECTED (spl_heap_consistency_validations (intern , false) != SUCCESS )) {
1310+ RETURN_THROWS ();
1311+ }
1312+ }
1313+
10731314/* iterator handler table */
10741315static const zend_object_iterator_funcs spl_heap_it_funcs = {
10751316 spl_heap_it_dtor ,
0 commit comments