|
@@ -60,6 +60,21 @@ typedef struct {
|
|
zend_class_entry *message_ce;
|
|
zend_class_entry *message_ce;
|
|
static zend_object_handlers message_object_handlers;
|
|
static zend_object_handlers message_object_handlers;
|
|
|
|
|
|
|
|
+static void Message_SuppressDefaultProperties(zend_class_entry *class_type) {
|
|
|
|
+ // We suppress all default properties, because all our properties are handled
|
|
|
|
+ // by our read_property handler.
|
|
|
|
+ //
|
|
|
|
+ // This also allows us to put our zend_object member at the beginning of our
|
|
|
|
+ // struct -- instead of putting it at the end with pointer fixups to access
|
|
|
|
+ // our own data, as recommended in the docs -- because Zend won't add any of
|
|
|
|
+ // its own storage directly after the zend_object if default_properties_count
|
|
|
|
+ // == 0.
|
|
|
|
+ //
|
|
|
|
+ // This is not officially supported, but since it simplifies the code, we'll
|
|
|
|
+ // do it for as long as it works in practice.
|
|
|
|
+ class_type->default_properties_count = 0;
|
|
|
|
+}
|
|
|
|
+
|
|
// PHP Object Handlers /////////////////////////////////////////////////////////
|
|
// PHP Object Handlers /////////////////////////////////////////////////////////
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -69,8 +84,7 @@ static zend_object_handlers message_object_handlers;
|
|
*/
|
|
*/
|
|
static zend_object* Message_create(zend_class_entry *class_type) {
|
|
static zend_object* Message_create(zend_class_entry *class_type) {
|
|
Message *intern = emalloc(sizeof(Message));
|
|
Message *intern = emalloc(sizeof(Message));
|
|
- // XXX(haberman): verify whether we actually want to take this route.
|
|
|
|
- class_type->default_properties_count = 0;
|
|
|
|
|
|
+ Message_SuppressDefaultProperties(class_type);
|
|
zend_object_std_init(&intern->std, class_type);
|
|
zend_object_std_init(&intern->std, class_type);
|
|
intern->std.handlers = &message_object_handlers;
|
|
intern->std.handlers = &message_object_handlers;
|
|
Arena_Init(&intern->arena);
|
|
Arena_Init(&intern->arena);
|
|
@@ -114,14 +128,14 @@ static void Message_get(Message *intern, const upb_fielddef *f, zval *rv) {
|
|
|
|
|
|
if (upb_fielddef_ismap(f)) {
|
|
if (upb_fielddef_ismap(f)) {
|
|
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
|
|
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
|
|
- MapField_GetPhpWrapper(rv, msgval.map, f, &intern->arena);
|
|
|
|
|
|
+ MapField_GetPhpWrapper(rv, msgval.map, MapType_Get(f), &intern->arena);
|
|
} else if (upb_fielddef_isseq(f)) {
|
|
} else if (upb_fielddef_isseq(f)) {
|
|
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
|
|
upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena);
|
|
- RepeatedField_GetPhpWrapper(rv, msgval.array, f, &intern->arena);
|
|
|
|
|
|
+ RepeatedField_GetPhpWrapper(rv, msgval.array, TypeInfo_Get(f),
|
|
|
|
+ &intern->arena);
|
|
} else {
|
|
} else {
|
|
upb_msgval msgval = upb_msg_get(intern->msg, f);
|
|
upb_msgval msgval = upb_msg_get(intern->msg, f);
|
|
- const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
|
|
|
|
- Convert_UpbToPhp(msgval, rv, upb_fielddef_type(f), subdesc, &intern->arena);
|
|
|
|
|
|
+ Convert_UpbToPhp(msgval, rv, TypeInfo_Get(f), &intern->arena);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -130,16 +144,13 @@ static bool Message_set(Message *intern, const upb_fielddef *f, zval *val) {
|
|
upb_msgval msgval;
|
|
upb_msgval msgval;
|
|
|
|
|
|
if (upb_fielddef_ismap(f)) {
|
|
if (upb_fielddef_ismap(f)) {
|
|
- msgval.map_val = MapField_GetUpbMap(val, f, arena);
|
|
|
|
|
|
+ msgval.map_val = MapField_GetUpbMap(val, MapType_Get(f), arena);
|
|
if (!msgval.map_val) return false;
|
|
if (!msgval.map_val) return false;
|
|
} else if (upb_fielddef_isseq(f)) {
|
|
} else if (upb_fielddef_isseq(f)) {
|
|
- msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
|
|
|
|
|
|
+ msgval.array_val = RepeatedField_GetUpbArray(val, TypeInfo_Get(f), arena);
|
|
if (!msgval.array_val) return false;
|
|
if (!msgval.array_val) return false;
|
|
} else {
|
|
} else {
|
|
- upb_fieldtype_t type = upb_fielddef_type(f);
|
|
|
|
- const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
|
|
|
|
- bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena);
|
|
|
|
- if (!ok) return false;
|
|
|
|
|
|
+ if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) return false;
|
|
}
|
|
}
|
|
|
|
|
|
upb_msg_set(intern->msg, f, msgval, arena);
|
|
upb_msg_set(intern->msg, f, msgval, arena);
|
|
@@ -149,11 +160,10 @@ static bool Message_set(Message *intern, const upb_fielddef *f, zval *val) {
|
|
static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m);
|
|
static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m);
|
|
|
|
|
|
/**
|
|
/**
|
|
- * ValueEq()()
|
|
|
|
|
|
+ * ValueEq()
|
|
*/
|
|
*/
|
|
-bool ValueEq(upb_msgval val1, upb_msgval val2, upb_fieldtype_t type,
|
|
|
|
- const upb_msgdef *m) {
|
|
|
|
- switch (type) {
|
|
|
|
|
|
+bool ValueEq(upb_msgval val1, upb_msgval val2, TypeInfo type) {
|
|
|
|
+ switch (type.type) {
|
|
case UPB_TYPE_BOOL:
|
|
case UPB_TYPE_BOOL:
|
|
return val1.bool_val == val2.bool_val;
|
|
return val1.bool_val == val2.bool_val;
|
|
case UPB_TYPE_INT32:
|
|
case UPB_TYPE_INT32:
|
|
@@ -172,7 +182,7 @@ bool ValueEq(upb_msgval val1, upb_msgval val2, upb_fieldtype_t type,
|
|
return val1.str_val.size == val2.str_val.size &&
|
|
return val1.str_val.size == val2.str_val.size &&
|
|
memcmp(val1.str_val.data, val2.str_val.data, val1.str_val.size) == 0;
|
|
memcmp(val1.str_val.data, val2.str_val.data, val1.str_val.size) == 0;
|
|
case UPB_TYPE_MESSAGE:
|
|
case UPB_TYPE_MESSAGE:
|
|
- return MessageEq(val1.msg_val, val2.msg_val, m);
|
|
|
|
|
|
+ return MessageEq(val1.msg_val, val2.msg_val, type.desc->msgdef);
|
|
default:
|
|
default:
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -190,8 +200,6 @@ static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m)
|
|
const upb_fielddef *f = upb_msg_iter_field(&i);
|
|
const upb_fielddef *f = upb_msg_iter_field(&i);
|
|
upb_msgval val1 = upb_msg_get(m1, f);
|
|
upb_msgval val1 = upb_msg_get(m1, f);
|
|
upb_msgval val2 = upb_msg_get(m2, f);
|
|
upb_msgval val2 = upb_msg_get(m2, f);
|
|
- upb_fieldtype_t type = upb_fielddef_type(f);
|
|
|
|
- const upb_msgdef *sub_m = upb_fielddef_msgsubdef(f);
|
|
|
|
|
|
|
|
if (upb_fielddef_haspresence(f)) {
|
|
if (upb_fielddef_haspresence(f)) {
|
|
if (upb_msg_has(m1, f) != upb_msg_has(m2, f)) {
|
|
if (upb_msg_has(m1, f) != upb_msg_has(m2, f)) {
|
|
@@ -201,18 +209,11 @@ static bool MessageEq(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m)
|
|
}
|
|
}
|
|
|
|
|
|
if (upb_fielddef_ismap(f)) {
|
|
if (upb_fielddef_ismap(f)) {
|
|
- const upb_fielddef *key_f = upb_msgdef_itof(sub_m, 1);
|
|
|
|
- const upb_fielddef *val_f = upb_msgdef_itof(sub_m, 2);
|
|
|
|
- upb_fieldtype_t key_type = upb_fielddef_type(key_f);
|
|
|
|
- upb_fieldtype_t val_type = upb_fielddef_type(val_f);
|
|
|
|
- const upb_msgdef *val_m = upb_fielddef_msgsubdef(val_f);
|
|
|
|
- if (!MapEq(val1.map_val, val2.map_val, key_type, val_type, val_m)) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ if (!MapEq(val1.map_val, val2.map_val, MapType_Get(f))) return false;
|
|
} else if (upb_fielddef_isseq(f)) {
|
|
} else if (upb_fielddef_isseq(f)) {
|
|
- if (!ArrayEq(val1.array_val, val2.array_val, type, sub_m)) return false;
|
|
|
|
|
|
+ if (!ArrayEq(val1.array_val, val2.array_val, TypeInfo_Get(f))) return false;
|
|
} else {
|
|
} else {
|
|
- if (!ValueEq(val1, val2, type, sub_m)) return false;
|
|
|
|
|
|
+ if (!ValueEq(val1, val2, TypeInfo_Get(f))) return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -392,6 +393,25 @@ static zval *Message_get_property_ptr_ptr(PROTO_VAL *object, PROTO_STR *member,
|
|
return NULL; // We do not have a properties table.
|
|
return NULL; // We do not have a properties table.
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Message_clone_obj()
|
|
|
|
+ *
|
|
|
|
+ * Object handler for cloning an object in PHP. Called when PHP code does:
|
|
|
|
+ *
|
|
|
|
+ * $msg2 = clone $msg;
|
|
|
|
+ */
|
|
|
|
+static zend_object *Message_clone_obj(zval *object) {
|
|
|
|
+ Message* intern = PROTO_MSG_P(object);
|
|
|
|
+ upb_msg *clone = upb_msg_new(intern->desc->msgdef, Arena_Get(&intern->arena));
|
|
|
|
+
|
|
|
|
+ // TODO: copy unknown fields?
|
|
|
|
+ // TODO: use official upb msg copy function
|
|
|
|
+ memcpy(clone, intern->msg, upb_msgdef_layout(intern->desc->msgdef)->size);
|
|
|
|
+ zval ret;
|
|
|
|
+ Message_GetPhpWrapper(&ret, intern->desc, clone, &intern->arena);
|
|
|
|
+ return Z_OBJ_P(&ret);
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Message_get_properties()
|
|
* Message_get_properties()
|
|
*
|
|
*
|
|
@@ -415,8 +435,7 @@ void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg,
|
|
|
|
|
|
if (!ObjCache_Get(msg, val)) {
|
|
if (!ObjCache_Get(msg, val)) {
|
|
Message *intern = emalloc(sizeof(Message));
|
|
Message *intern = emalloc(sizeof(Message));
|
|
- // XXX(haberman): verify whether we actually want to take this route.
|
|
|
|
- desc->class_entry->default_properties_count = 0;
|
|
|
|
|
|
+ Message_SuppressDefaultProperties(desc->class_entry);
|
|
zend_object_std_init(&intern->std, desc->class_entry);
|
|
zend_object_std_init(&intern->std, desc->class_entry);
|
|
intern->std.handlers = &message_object_handlers;
|
|
intern->std.handlers = &message_object_handlers;
|
|
ZVAL_COPY(&intern->arena, arena);
|
|
ZVAL_COPY(&intern->arena, arena);
|
|
@@ -521,15 +540,13 @@ bool Message_InitFromPhp(upb_msg *msg, const upb_msgdef *m, zval *init,
|
|
}
|
|
}
|
|
|
|
|
|
if (upb_fielddef_ismap(f)) {
|
|
if (upb_fielddef_ismap(f)) {
|
|
- msgval.map_val = MapField_GetUpbMap(val, f, arena);
|
|
|
|
|
|
+ msgval.map_val = MapField_GetUpbMap(val, MapType_Get(f), arena);
|
|
if (!msgval.map_val) return false;
|
|
if (!msgval.map_val) return false;
|
|
} else if (upb_fielddef_isseq(f)) {
|
|
} else if (upb_fielddef_isseq(f)) {
|
|
- msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
|
|
|
|
|
|
+ msgval.array_val = RepeatedField_GetUpbArray(val, TypeInfo_Get(f), arena);
|
|
if (!msgval.array_val) return false;
|
|
if (!msgval.array_val) return false;
|
|
} else {
|
|
} else {
|
|
- const Descriptor *desc = Descriptor_GetFromFieldDef(f);
|
|
|
|
- upb_fieldtype_t type = upb_fielddef_type(f);
|
|
|
|
- if (!Convert_PhpToUpbAutoWrap(val, &msgval, type, desc, arena)) {
|
|
|
|
|
|
+ if (!Convert_PhpToUpbAutoWrap(val, &msgval, TypeInfo_Get(f), arena)) {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -827,10 +844,9 @@ PHP_METHOD(Message, readWrapperValue) {
|
|
const upb_msg *wrapper = upb_msg_get(intern->msg, f).msg_val;
|
|
const upb_msg *wrapper = upb_msg_get(intern->msg, f).msg_val;
|
|
const upb_msgdef *m = upb_fielddef_msgsubdef(f);
|
|
const upb_msgdef *m = upb_fielddef_msgsubdef(f);
|
|
const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
|
|
const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
|
|
- const upb_fieldtype_t val_type = upb_fielddef_type(val_f);
|
|
|
|
upb_msgval msgval = upb_msg_get(wrapper, val_f);
|
|
upb_msgval msgval = upb_msg_get(wrapper, val_f);
|
|
zval ret;
|
|
zval ret;
|
|
- Convert_UpbToPhp(msgval, &ret, val_type, NULL, &intern->arena);
|
|
|
|
|
|
+ Convert_UpbToPhp(msgval, &ret, TypeInfo_Get(val_f), &intern->arena);
|
|
RETURN_ZVAL(&ret, 1, 0);
|
|
RETURN_ZVAL(&ret, 1, 0);
|
|
} else {
|
|
} else {
|
|
RETURN_NULL();
|
|
RETURN_NULL();
|
|
@@ -883,10 +899,9 @@ PHP_METHOD(Message, writeWrapperValue) {
|
|
} else {
|
|
} else {
|
|
const upb_msgdef *m = upb_fielddef_msgsubdef(f);
|
|
const upb_msgdef *m = upb_fielddef_msgsubdef(f);
|
|
const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
|
|
const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
|
|
- upb_fieldtype_t val_type = upb_fielddef_type(val_f);
|
|
|
|
upb_msg *wrapper;
|
|
upb_msg *wrapper;
|
|
|
|
|
|
- if (!Convert_PhpToUpb(val, &msgval, val_type, NULL, arena)) {
|
|
|
|
|
|
+ if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(val_f), arena)) {
|
|
return; // Error is already set.
|
|
return; // Error is already set.
|
|
}
|
|
}
|
|
|
|
|
|
@@ -996,9 +1011,7 @@ PHP_METHOD(Message, readOneof) {
|
|
|
|
|
|
{
|
|
{
|
|
upb_msgval msgval = upb_msg_get(intern->msg, f);
|
|
upb_msgval msgval = upb_msg_get(intern->msg, f);
|
|
- const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
|
|
|
|
- Convert_UpbToPhp(msgval, &ret, upb_fielddef_type(f), subdesc,
|
|
|
|
- &intern->arena);
|
|
|
|
|
|
+ Convert_UpbToPhp(msgval, &ret, TypeInfo_Get(f), &intern->arena);
|
|
}
|
|
}
|
|
|
|
|
|
RETURN_ZVAL(&ret, 1, 0);
|
|
RETURN_ZVAL(&ret, 1, 0);
|
|
@@ -1039,8 +1052,7 @@ PHP_METHOD(Message, writeOneof) {
|
|
|
|
|
|
f = upb_msgdef_itof(intern->desc->msgdef, field_num);
|
|
f = upb_msgdef_itof(intern->desc->msgdef, field_num);
|
|
|
|
|
|
- if (!Convert_PhpToUpb(val, &msgval, upb_fielddef_type(f),
|
|
|
|
- Descriptor_GetFromFieldDef(f), arena)) {
|
|
|
|
|
|
+ if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(f), arena)) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1247,8 +1259,8 @@ PHP_METHOD(google_protobuf_Timestamp, fromDateTime) {
|
|
|
|
|
|
if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1,
|
|
if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1,
|
|
datetime) == FAILURE ||
|
|
datetime) == FAILURE ||
|
|
- !Convert_PhpToUpb(&retval, ×tamp_seconds, UPB_TYPE_INT64, NULL,
|
|
|
|
- NULL)) {
|
|
|
|
|
|
+ !Convert_PhpToUpb(&retval, ×tamp_seconds,
|
|
|
|
+ TypeInfo_FromType(UPB_TYPE_INT64), NULL)) {
|
|
zend_error(E_ERROR, "Cannot get timestamp from DateTime.");
|
|
zend_error(E_ERROR, "Cannot get timestamp from DateTime.");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1273,8 +1285,8 @@ PHP_METHOD(google_protobuf_Timestamp, fromDateTime) {
|
|
|
|
|
|
if (call_user_function(EG(function_table), NULL, &function_name, &retval, 2,
|
|
if (call_user_function(EG(function_table), NULL, &function_name, &retval, 2,
|
|
params) == FAILURE ||
|
|
params) == FAILURE ||
|
|
- !Convert_PhpToUpb(&retval, ×tamp_nanos, UPB_TYPE_INT32, NULL,
|
|
|
|
- NULL)) {
|
|
|
|
|
|
+ !Convert_PhpToUpb(&retval, ×tamp_nanos,
|
|
|
|
+ TypeInfo_FromType(UPB_TYPE_INT32), NULL)) {
|
|
zend_error(E_ERROR, "Cannot format DateTime.");
|
|
zend_error(E_ERROR, "Cannot format DateTime.");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1360,6 +1372,7 @@ void Message_ModuleInit() {
|
|
h->unset_property = Message_unset_property;
|
|
h->unset_property = Message_unset_property;
|
|
h->get_properties = Message_get_properties;
|
|
h->get_properties = Message_get_properties;
|
|
h->get_property_ptr_ptr = Message_get_property_ptr_ptr;
|
|
h->get_property_ptr_ptr = Message_get_property_ptr_ptr;
|
|
|
|
+ h->clone_obj = Message_clone_obj;
|
|
|
|
|
|
WellKnownTypes_ModuleInit(); /* From wkt.inc. */
|
|
WellKnownTypes_ModuleInit(); /* From wkt.inc. */
|
|
}
|
|
}
|