Skip to content
This repository was archived by the owner on Jan 12, 2021. It is now read-only.

Commit 3a62bfa

Browse files
authored
Fixed appending and setting value (#90)
1 parent 9799c32 commit 3a62bfa

File tree

1 file changed

+54
-43
lines changed

1 file changed

+54
-43
lines changed

protobuf.c

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@
1919
#define Z_UNSET_ISREF(z) PZVAL_IS_REF(&(z)) = 0
2020
#endif
2121

22+
#ifndef ZVAL_COPY_VALUE
23+
#define ZVAL_COPY_VALUE(z, v) \
24+
do { \
25+
(z)->value = (v)->value; \
26+
Z_TYPE_P(z) = Z_TYPE_P(v); \
27+
} while (0)
28+
#endif
29+
30+
#ifndef INIT_PZVAL_COPY
31+
#define INIT_PZVAL_COPY(z, v) \
32+
do { \
33+
ZVAL_COPY_VALUE(z, v); \
34+
Z_SET_REFCOUNT_P(z, 1); \
35+
Z_UNSET_ISREF_P(z); \
36+
} while (0)
37+
#endif
38+
2239
#define PB_COMPILE_ERROR(message, ...) PB_COMPILE_ERROR_EX(getThis(), message, __VA_ARGS__)
2340
#define PB_COMPILE_ERROR_EX(this, message, ...) \
2441
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%s: compile error - " #message, Z_OBJCE_P(this)->name, __VA_ARGS__)
@@ -58,7 +75,7 @@ enum
5875

5976
zend_class_entry *pb_entry;
6077

61-
static int pb_assign_value(zval *this, zval *dst, zval *src, uint32_t field_number);
78+
static zval *pb_prepare_value(zval *this, uint32_t field_number, zval *value);
6279
static int pb_print_field_value(zval **value, long level, zend_bool only_set);
6380
static int pb_dump_field_value(zval **value, long level, zend_bool only_set);
6481
static int pb_print_debug_field_value(zval **value, long level);
@@ -90,7 +107,7 @@ PHP_METHOD(ProtobufMessage, __construct)
90107
PHP_METHOD(ProtobufMessage, append)
91108
{
92109
long field_number;
93-
zval **array, *value, **values, *val;
110+
zval **array, *prepared_value, *value, **values;
94111

95112
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &field_number, &value) == FAILURE) {
96113
RETURN_THIS();
@@ -105,13 +122,10 @@ PHP_METHOD(ProtobufMessage, append)
105122
if ((array = pb_get_value(getThis(), values, field_number)) == NULL)
106123
RETURN_THIS();
107124

108-
MAKE_STD_ZVAL(val);
109-
if (pb_assign_value(getThis(), val, value, field_number) != 0) {
110-
zval_ptr_dtor(&val);
111-
RETURN_THIS();
125+
if ((prepared_value = pb_prepare_value(getThis(), field_number, value)) != NULL) {
126+
add_next_index_zval(*array, prepared_value);
112127
}
113128

114-
add_next_index_zval(*array, val);
115129
RETURN_THIS();
116130
}
117131

@@ -558,7 +572,7 @@ PHP_METHOD(ProtobufMessage, serializeToString)
558572
PHP_METHOD(ProtobufMessage, set)
559573
{
560574
long field_number = -1;
561-
zval **old_value, *value, **values;
575+
zval *prepared_value, **old_value, *value, **values, *val;
562576

563577
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &field_number, &value) == FAILURE) {
564578
RETURN_THIS();
@@ -567,17 +581,20 @@ PHP_METHOD(ProtobufMessage, set)
567581
if ((values = pb_get_values(getThis())) == NULL)
568582
RETURN_THIS();
569583

570-
if ((old_value = pb_get_value(getThis(), values, field_number)) == NULL)
571-
RETURN_THIS();
572-
573584
if (Z_TYPE_P(value) == IS_NULL) {
585+
// null value means 'no value', therefore should not be converted
586+
if ((old_value = pb_get_value(getThis(), values, field_number)) == NULL) {
587+
RETURN_THIS();
588+
}
574589
if (Z_TYPE_PP(old_value) != IS_NULL) {
575-
zval_dtor(*old_value);
576-
INIT_ZVAL(**old_value);
590+
if ((prepared_value = pb_prepare_value(getThis(), field_number, value)) != NULL) {
591+
add_index_zval(*values, field_number, prepared_value);
592+
}
577593
}
578594
} else {
579-
zval_dtor(*old_value);
580-
pb_assign_value(getThis(), *old_value, value, field_number);
595+
if ((prepared_value = pb_prepare_value(getThis(), field_number, value)) != NULL) {
596+
add_index_zval(*values, field_number, prepared_value);
597+
}
581598
}
582599

583600
RETURN_THIS();
@@ -685,68 +702,62 @@ zend_module_entry protobuf_module_entry = {
685702
ZEND_GET_MODULE(protobuf)
686703
#endif
687704

688-
static int pb_assign_value(zval *this, zval *dst, zval *src, uint32_t field_number)
705+
static zval *pb_prepare_value(zval *this, uint32_t field_number, zval *value)
689706
{
690-
zval **field_descriptor, *field_descriptors, tmp, **type;
707+
zval *converted_value, **field_descriptor, *field_descriptors, **type;
708+
long expected_type;
691709
TSRMLS_FETCH();
692710

693711
if ((field_descriptors = pb_get_field_descriptors(this)) == NULL)
694-
goto fail0;
712+
goto fail;
695713

696714
if ((field_descriptor = pb_get_field_descriptor(this, field_descriptors, field_number)) == NULL)
697-
goto fail0;
715+
goto fail;
698716

699717
if ((type = pb_get_field_type(this, field_descriptor, field_number)) == NULL)
700-
goto fail0;
701-
702-
tmp = *src;
703-
zval_copy_ctor(&tmp);
704-
Z_SET_REFCOUNT(tmp, 1);
705-
Z_UNSET_ISREF(tmp);
718+
goto fail;
706719

707720
if (Z_TYPE_PP(type) == IS_LONG) {
708721
switch (Z_LVAL_PP(type))
709722
{
710723
case PB_TYPE_DOUBLE:
711724
case PB_TYPE_FLOAT:
712-
if (Z_TYPE_P(&tmp) != IS_DOUBLE)
713-
convert_to_explicit_type(&tmp, IS_DOUBLE);
714-
725+
expected_type = IS_DOUBLE;
715726
break;
716727

717728
case PB_TYPE_FIXED32:
718729
case PB_TYPE_INT:
719730
case PB_TYPE_FIXED64:
720731
case PB_TYPE_SIGNED_INT:
721732
case PB_TYPE_BOOL:
722-
if (Z_TYPE_P(&tmp) != IS_LONG)
723-
convert_to_explicit_type(&tmp, IS_LONG);
724-
733+
expected_type = IS_LONG;
725734
break;
726735

727736
case PB_TYPE_STRING:
728-
if (Z_TYPE_P(&tmp) != IS_STRING)
729-
convert_to_explicit_type(&tmp, IS_STRING);
730-
737+
expected_type = IS_STRING;
731738
break;
732739

733740
default:
734741
PB_COMPILE_ERROR_EX(this, "unexpected '%s' field type %d in field descriptor", pb_get_field_name(this, field_number), zend_get_type_by_const(Z_LVAL_PP(type)));
735-
goto fail1;
742+
goto fail;
736743
}
737-
738744
} else if (Z_TYPE_PP(type) != IS_STRING) {
739745
PB_COMPILE_ERROR_EX(this, "unexpected %s type of '%s' field type in field descriptor", zend_get_type_by_const(Z_TYPE_PP(type)), pb_get_field_name(this, field_number));
740-
goto fail1;
746+
goto fail;
741747
}
742748

743-
*dst = tmp;
749+
if (Z_TYPE_P(value) != expected_type) {
750+
ALLOC_ZVAL(converted_value);
751+
INIT_PZVAL_COPY(converted_value, value);
752+
zval_copy_ctor(converted_value);
753+
convert_to_explicit_type(converted_value, expected_type);
754+
return converted_value;
755+
}
744756

745-
return 0;
746-
fail1:
747-
zval_dtor(&tmp);
748-
fail0:
749-
return -1;
757+
Z_ADDREF_P(value);
758+
return value;
759+
fail:
760+
return NULL;
750761
}
751762

752763
static int pb_print_field_value(zval **value, long level, zend_bool only_set)

0 commit comments

Comments
 (0)