@@ -282,15 +282,118 @@ void build_class_from_descriptor(
282
282
// PHP Methods
283
283
// -----------------------------------------------------------------------------
284
284
285
+ void Message_construct (zval * msg , zval * array_wrapper ) {
286
+ zend_class_entry * ce = Z_OBJCE_P (msg );
287
+ MessageHeader * intern = NULL ;
288
+ if (EXPECTED (class_added (ce ))) {
289
+ intern = UNBOX (MessageHeader , msg );
290
+ custom_data_init (ce , intern PHP_PROTO_TSRMLS_CC );
291
+ }
292
+
293
+ if (array_wrapper == NULL ) {
294
+ return ;
295
+ }
296
+
297
+ HashTable * array = Z_ARRVAL_P (array_wrapper );
298
+ HashPosition pointer ;
299
+ zval key ;
300
+ void * value ;
301
+ const upb_fielddef * field ;
302
+
303
+ for (zend_hash_internal_pointer_reset_ex (array , & pointer );
304
+ php_proto_zend_hash_get_current_data_ex (array , (void * * )& value ,
305
+ & pointer ) == SUCCESS ;
306
+ zend_hash_move_forward_ex (array , & pointer )) {
307
+ zend_hash_get_current_key_zval_ex (array , & key , & pointer );
308
+ field = upb_msgdef_ntofz (intern -> descriptor -> msgdef , Z_STRVAL_P (& key ));
309
+ if (field == NULL ) {
310
+ zend_error (E_USER_ERROR , "Unknown field: %s" , Z_STRVAL_P (& key ));
311
+ }
312
+ if (upb_fielddef_ismap (field )) {
313
+ PHP_PROTO_FAKE_SCOPE_BEGIN (Z_OBJCE_P (msg ));
314
+ zval * submap = message_get_property_internal (msg , & key TSRMLS_CC );
315
+ PHP_PROTO_FAKE_SCOPE_END ;
316
+ HashTable * subtable = HASH_OF (
317
+ CACHED_PTR_TO_ZVAL_PTR ((CACHED_VALUE * )value ));
318
+ HashPosition subpointer ;
319
+ zval subkey ;
320
+ void * memory ;
321
+ for (zend_hash_internal_pointer_reset_ex (subtable , & subpointer );
322
+ php_proto_zend_hash_get_current_data_ex (subtable , (void * * )& memory ,
323
+ & subpointer ) == SUCCESS ;
324
+ zend_hash_move_forward_ex (subtable , & subpointer )) {
325
+ zend_hash_get_current_key_zval_ex (subtable , & subkey , & subpointer );
326
+ map_field_handlers -> write_dimension (
327
+ submap , & subkey ,
328
+ CACHED_PTR_TO_ZVAL_PTR ((CACHED_VALUE * )memory ) TSRMLS_CC );
329
+ zval_dtor (& subkey );
330
+ }
331
+ } else if (upb_fielddef_isseq (field )) {
332
+ PHP_PROTO_FAKE_SCOPE_BEGIN (Z_OBJCE_P (msg ));
333
+ zval * subarray = message_get_property_internal (msg , & key TSRMLS_CC );
334
+ PHP_PROTO_FAKE_SCOPE_END ;
335
+ HashTable * subtable = HASH_OF (
336
+ CACHED_PTR_TO_ZVAL_PTR ((CACHED_VALUE * )value ));
337
+ HashPosition subpointer ;
338
+ void * memory ;
339
+ for (zend_hash_internal_pointer_reset_ex (subtable , & subpointer );
340
+ php_proto_zend_hash_get_current_data_ex (subtable , (void * * )& memory ,
341
+ & subpointer ) == SUCCESS ;
342
+ zend_hash_move_forward_ex (subtable , & subpointer )) {
343
+ repeated_field_handlers -> write_dimension (
344
+ subarray , NULL ,
345
+ CACHED_PTR_TO_ZVAL_PTR ((CACHED_VALUE * )memory ) TSRMLS_CC );
346
+ }
347
+ } else if (upb_fielddef_issubmsg (field )) {
348
+ const upb_msgdef * submsgdef = upb_fielddef_msgsubdef (field );
349
+ PHP_PROTO_HASHTABLE_VALUE desc_php = get_def_obj (submsgdef );
350
+ Descriptor * desc = UNBOX_HASHTABLE_VALUE (Descriptor , desc_php );
351
+ zend_property_info * property_info ;
352
+ PHP_PROTO_FAKE_SCOPE_BEGIN (Z_OBJCE_P (msg ));
353
+ #if PHP_MAJOR_VERSION < 7
354
+ property_info =
355
+ zend_get_property_info (Z_OBJCE_P (msg ), & key , true TSRMLS_CC );
356
+ #else
357
+ property_info =
358
+ zend_get_property_info (Z_OBJCE_P (msg ), Z_STR_P (& key ), true);
359
+ #endif
360
+ PHP_PROTO_FAKE_SCOPE_END ;
361
+ CACHED_VALUE * cached = OBJ_PROP (Z_OBJ_P (msg ), property_info -> offset );
362
+ #if PHP_MAJOR_VERSION < 7
363
+ SEPARATE_ZVAL_IF_NOT_REF (cached );
364
+ #endif
365
+ zval * submsg = CACHED_PTR_TO_ZVAL_PTR (cached );
366
+ ZVAL_OBJ (submsg , desc -> klass -> create_object (desc -> klass TSRMLS_CC ));
367
+ Message_construct (submsg , NULL );
368
+ MessageHeader * from = UNBOX (MessageHeader ,
369
+ CACHED_PTR_TO_ZVAL_PTR ((CACHED_VALUE * )value ));
370
+ MessageHeader * to = UNBOX (MessageHeader , submsg );
371
+ if (from -> descriptor != to -> descriptor ) {
372
+ zend_error (E_USER_ERROR , "Cannot merge messages with different class." );
373
+ return ;
374
+ }
375
+
376
+ layout_merge (from -> descriptor -> layout , from , to TSRMLS_CC );
377
+ } else {
378
+ message_set_property_internal (msg , & key ,
379
+ CACHED_PTR_TO_ZVAL_PTR ((CACHED_VALUE * )value ) TSRMLS_CC );
380
+ }
381
+ zval_dtor (& key );
382
+ }
383
+ }
384
+
285
385
// At the first time the message is created, the class entry hasn't been
286
386
// modified. As a result, the first created instance will be a normal zend
287
387
// object. Here, we manually modify it to our message in such a case.
288
388
PHP_METHOD (Message , __construct ) {
289
- zend_class_entry * ce = Z_OBJCE_P (getThis ());
290
- if (EXPECTED (class_added (ce ))) {
291
- MessageHeader * intern = UNBOX (MessageHeader , getThis ());
292
- custom_data_init (ce , intern PHP_PROTO_TSRMLS_CC );
389
+ // Init message with array
390
+ zval * array_wrapper ;
391
+ if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC , "a!" , & array_wrapper ,
392
+ message_type ) == FAILURE ) {
393
+ return ;
293
394
}
395
+
396
+ Message_construct (getThis (), array_wrapper );
294
397
}
295
398
296
399
PHP_METHOD (Message , clear ) {
0 commit comments