aboutsummaryrefslogtreecommitdiffhomepage
path: root/php/ext/google/protobuf/storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'php/ext/google/protobuf/storage.c')
-rw-r--r--php/ext/google/protobuf/storage.c88
1 files changed, 84 insertions, 4 deletions
diff --git a/php/ext/google/protobuf/storage.c b/php/ext/google/protobuf/storage.c
index 6c789bcb..e46dbf70 100644
--- a/php/ext/google/protobuf/storage.c
+++ b/php/ext/google/protobuf/storage.c
@@ -199,6 +199,57 @@ bool native_slot_set_by_array(upb_fieldtype_t type,
Z_ADDREF_P(value);
}
#else
+ DEREF(memory, zval*) = value;
+ ++GC_REFCOUNT(Z_OBJ_P(value));
+#endif
+ break;
+ }
+ default:
+ return native_slot_set(type, klass, memory, value TSRMLS_CC);
+ }
+ return true;
+}
+
+bool native_slot_set_by_map(upb_fieldtype_t type, const zend_class_entry* klass,
+ void* memory, zval* value TSRMLS_DC) {
+ switch (type) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ if (!protobuf_convert_to_string(value)) {
+ return false;
+ }
+ if (type == UPB_TYPE_STRING &&
+ !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) {
+ zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
+ return false;
+ }
+
+ // Handles repeated/map string field. Memory provided by
+ // RepeatedField/Map is not initialized.
+#if PHP_MAJOR_VERSION < 7
+ MAKE_STD_ZVAL(DEREF(memory, zval*));
+ PHP_PROTO_ZVAL_STRINGL(DEREF(memory, zval*), Z_STRVAL_P(value),
+ Z_STRLEN_P(value), 1);
+#else
+ *(zend_string**)memory = zend_string_dup(Z_STR_P(value), 0);
+#endif
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ if (Z_TYPE_P(value) != IS_OBJECT) {
+ zend_error(E_USER_ERROR, "Given value is not message.");
+ return false;
+ }
+ if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) {
+ zend_error(E_USER_ERROR, "Given message does not have correct class.");
+ return false;
+ }
+#if PHP_MAJOR_VERSION < 7
+ if (EXPECTED(DEREF(memory, zval*) != value)) {
+ DEREF(memory, zval*) = value;
+ Z_ADDREF_P(value);
+ }
+#else
DEREF(memory, zend_object*) = Z_OBJ_P(value);
++GC_REFCOUNT(Z_OBJ_P(value));
#endif
@@ -348,8 +399,7 @@ void native_slot_get_by_array(upb_fieldtype_t type, const void* memory,
ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0);
}
#else
- ++GC_REFCOUNT(*(zend_object**)memory);
- ZVAL_OBJ(cache, *(zend_object**)memory);
+ ZVAL_COPY(CACHED_PTR_TO_ZVAL_PTR(cache), memory);
#endif
return;
}
@@ -371,6 +421,26 @@ void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory,
}
}
+void native_slot_get_by_map_value(upb_fieldtype_t type, const void* memory,
+ CACHED_VALUE* cache TSRMLS_DC) {
+ switch (type) {
+ case UPB_TYPE_MESSAGE: {
+#if PHP_MAJOR_VERSION < 7
+ zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
+ if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) {
+ ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0);
+ }
+#else
+ ++GC_REFCOUNT(*(zend_object**)memory);
+ ZVAL_OBJ(cache, *(zend_object**)memory);
+#endif
+ return;
+ }
+ default:
+ native_slot_get_by_array(type, memory, cache TSRMLS_CC);
+ }
+}
+
void native_slot_get_default(upb_fieldtype_t type,
CACHED_VALUE* cache TSRMLS_DC) {
switch (type) {
@@ -952,8 +1022,18 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
void* to_memory =
ALLOC_N(char, native_slot_size(upb_fielddef_type(field)));
memset(to_memory, 0, native_slot_size(upb_fielddef_type(field)));
- php_proto_zend_hash_index_find(PHP_PROTO_HASH_OF(from_array->array),
- j, (void**)&from_memory);
+
+ if (to_array->type == UPB_TYPE_MESSAGE) {
+ php_proto_zend_hash_index_find_zval(
+ PHP_PROTO_HASH_OF(from_array->array), j, (void**)&from_memory);
+#if PHP_MAJOR_VERSION >= 7
+ from_memory = &Z_OBJ_P((zval*)from_memory);
+#endif
+ } else {
+ php_proto_zend_hash_index_find_mem(
+ PHP_PROTO_HASH_OF(from_array->array), j, (void**)&from_memory);
+ }
+
native_slot_merge_by_array(field, from_memory,
to_memory PHP_PROTO_TSRMLS_CC);
repeated_field_push_native(to_array, to_memory);