Passes all tests.
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c index c3ffd31..1ae5c4d 100644 --- a/php/ext/google/protobuf/def.c +++ b/php/ext/google/protobuf/def.c
@@ -1011,6 +1011,21 @@ }; // ----------------------------------------------------------------------------- +// InternalDescriptorPool +// ----------------------------------------------------------------------------- + +// For the C extension, Google\Protobuf\Internal\DescriptorPool is not a +// separate instantiable object, it just returns a +// Google\Protobuf\DescriptorPool. + +zend_class_entry *InternalDescriptorPool_class_entry; + +static zend_function_entry InternalDescriptorPool_methods[] = { + PHP_ME(DescriptorPool, getGeneratedPool, NULL, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) +}; + +// ----------------------------------------------------------------------------- // GPBType // ----------------------------------------------------------------------------- @@ -1071,7 +1086,7 @@ h = &FieldDescriptor_object_handlers; memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); - INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool", + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\DescriptorPool", DescriptorPool_methods); DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce); DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL; @@ -1080,6 +1095,10 @@ memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); h->dtor_obj = DescriptorPool_destructor; + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool", + InternalDescriptorPool_methods); + InternalDescriptorPool_class_entry = zend_register_internal_class(&tmp_ce); + // GPBType. #define STR(str) (str), strlen(str) zend_class_entry class_type;
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c index 8dd8edf..3cc5a77 100644 --- a/php/ext/google/protobuf/message.c +++ b/php/ext/google/protobuf/message.c
@@ -540,6 +540,12 @@ } } +static void Message_Initialize(Message *intern, const Descriptor *desc) { + intern->desc = desc; + intern->msg = upb_msg_new(desc->msgdef, Arena_Get(&intern->arena)); + ObjCache_Add(intern->msg, &intern->std); +} + /** * Message::__construct() * @@ -549,13 +555,10 @@ PHP_METHOD(Message, __construct) { Message* intern = (Message*)Z_OBJ_P(getThis()); const Descriptor* desc = Descriptor_GetFromClassEntry(Z_OBJCE_P(getThis())); - const upb_msgdef *msgdef = desc->msgdef; upb_arena *arena = Arena_Get(&intern->arena); zval *init_arr = NULL; - intern->desc = desc; - intern->msg = upb_msg_new(msgdef, arena); - ObjCache_Add(intern->msg, &intern->std); + Message_Initialize(intern, desc); if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &init_arr) == FAILURE) { return; @@ -1024,31 +1027,55 @@ static upb_msgval Message_getval(Message *intern, const char *field_name) { const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, field_name); + PBPHP_ASSERT(f); return upb_msg_get(intern->msg, f); } +static void Message_setval(Message *intern, const char *field_name, + upb_msgval val) { + const upb_fielddef *f = upb_msgdef_ntofz(intern->desc->msgdef, field_name); + PBPHP_ASSERT(f); + return upb_msg_set(intern->msg, f, val, Arena_Get(&intern->arena)); +} + +static upb_msgval StringVal(upb_strview view) { + upb_msgval ret; + ret.str_val = view; + return ret; +} + +static bool TryStripUrlPrefix(upb_strview *str) { + size_t size = strlen(TYPE_URL_PREFIX); + if (str->size < size || memcmp(TYPE_URL_PREFIX, str->data, size) != 0) { + return false; + } + str->data += size; + str->size -= size; + return true; +} + +static bool StrViewEq(upb_strview view, const char *str) { + size_t size = strlen(str); + return view.size == size && memcmp(view.data, str, size) == 0; +} + PHP_METHOD(google_protobuf_Any, unpack) { Message* intern = (Message*)Z_OBJ_P(getThis()); upb_strview type_url = Message_getval(intern, "type_url").str_val; upb_strview value = Message_getval(intern, "value").str_val; - size_t prefix_len = strlen(TYPE_URL_PREFIX); upb_symtab *symtab = DescriptorPool_GetSymbolTable(); const upb_msgdef *m; Descriptor *desc; - zend_class_entry *klass; zval ret; // Ensure that type_url has TYPE_URL_PREFIX as a prefix. - if (type_url.size < prefix_len || - strncmp(TYPE_URL_PREFIX, type_url.data, prefix_len) != 0) { + if (!TryStripUrlPrefix(&type_url)) { zend_throw_exception( NULL, "Type url needs to be type.googleapis.com/fully-qualified", 0 TSRMLS_CC); return; } - type_url.size -= prefix_len; - type_url.data += prefix_len; m = upb_symtab_lookupmsg2(symtab, type_url.data, type_url.size); if (m == NULL) { @@ -1059,9 +1086,11 @@ } desc = Descriptor_GetFromMessageDef(m); - klass = desc->class_entry; - ZVAL_OBJ(&ret, klass->create_object(klass)); - Message *msg = (Message*)Z_OBJ_P(&ret); + PBPHP_ASSERT(desc->class_entry->create_object == Message_create); + zend_object *obj = Message_create(desc->class_entry); + Message *msg = (Message*)obj; + Message_Initialize(msg, desc); + ZVAL_OBJ(&ret, obj); // Get value. if (!upb_decode(value.data, value.size, msg->msg, @@ -1076,9 +1105,15 @@ RETURN_ZVAL(&ret, 1, 0); } -/* -PHP_METHOD(Any, pack) { - zval* val; +PHP_METHOD(google_protobuf_Any, pack) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zval *val; + Message *msg; + upb_strview value; + upb_strview type_url; + const char *full_name; + char *buf; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &val) == FAILURE) { @@ -1090,76 +1125,153 @@ return; } - // Set value by serialized data. - zval data; - serialize_to_string(val, &data TSRMLS_CC); + msg = (Message*)Z_OBJ_P(val); - zval member; - PHP_PROTO_ZVAL_STRING(&member, "value", 1); + // Serialize and set value. + value.data = upb_encode(msg->msg, upb_msgdef_layout(msg->desc->msgdef), arena, + &value.size); + Message_setval(intern, "value", StringVal(value)); - PHP_PROTO_FAKE_SCOPE_BEGIN(any_type); - message_handlers->write_property(getThis(), &member, &data, - NULL PHP_PROTO_TSRMLS_CC); - zval_dtor(&data); - zval_dtor(&member); - PHP_PROTO_FAKE_SCOPE_END; - - // Set type url. - DescriptorInternal* desc = get_ce_desc(Z_OBJCE_P(val)); - const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef); - size_t type_url_len = - strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1; - char* type_url = ALLOC_N(char, type_url_len); - sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name); - zval type_url_php; - PHP_PROTO_ZVAL_STRING(&type_url_php, type_url, 1); - PHP_PROTO_ZVAL_STRING(&member, "type_url", 1); - - PHP_PROTO_FAKE_SCOPE_RESTART(any_type); - message_handlers->write_property(getThis(), &member, &type_url_php, - NULL PHP_PROTO_TSRMLS_CC); - zval_dtor(&type_url_php); - zval_dtor(&member); - PHP_PROTO_FAKE_SCOPE_END; - FREE(type_url); + // Set type url: type_url_prefix + fully_qualified_name + full_name = upb_msgdef_fullname(msg->desc->msgdef); + type_url.size = strlen(TYPE_URL_PREFIX) + strlen(full_name); + buf = upb_arena_malloc(arena, type_url.size + 1); + memcpy(buf, TYPE_URL_PREFIX, strlen(TYPE_URL_PREFIX)); + memcpy(buf + strlen(TYPE_URL_PREFIX), full_name, strlen(full_name)); + type_url.data = buf; + Message_setval(intern, "type_url", StringVal(type_url)); } -PHP_METHOD(Any, is) { +PHP_METHOD(google_protobuf_Any, is) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_strview type_url = Message_getval(intern, "type_url").str_val; zend_class_entry *klass = NULL; + const upb_msgdef *m; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "C", &klass) == FAILURE) { return; } - DescriptorInternal* desc = get_ce_desc(klass); - if (desc == NULL) { + m = NameMap_GetMessage(klass); + + if (m == NULL) { RETURN_BOOL(false); } - // Create corresponded type url. - const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef); - size_t type_url_len = - strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1; - char* type_url = ALLOC_N(char, type_url_len); - sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name); - - // Fetch stored type url. - zval member; - PHP_PROTO_ZVAL_STRING(&member, "type_url", 1); - PHP_PROTO_FAKE_SCOPE_BEGIN(any_type); - zval* value = - php_proto_message_read_property(getThis(), &member PHP_PROTO_TSRMLS_CC); - zval_dtor(&member); - PHP_PROTO_FAKE_SCOPE_END; - - // Compare two type url. - bool is = strcmp(type_url, Z_STRVAL_P(value)) == 0; - FREE(type_url); - - RETURN_BOOL(is); + RETURN_BOOL(TryStripUrlPrefix(&type_url) && + StrViewEq(type_url, upb_msgdef_fullname(m))); } -*/ + +PHP_METHOD(google_protobuf_Timestamp, fromDateTime) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + zval* datetime; + const char *classname = "\\DatetimeInterface"; + zend_string *classname_str = zend_string_init(classname, strlen(classname), 0); + zend_class_entry *date_interface_ce = zend_lookup_class(classname_str); + + if (date_interface_ce == NULL) { + zend_error(E_ERROR, "Make sure date extension is enabled."); + return; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &datetime, + date_interface_ce) == FAILURE) { + zend_error(E_USER_ERROR, "Expect DatetimeInterface."); + return; + } + + upb_msgval timestamp_seconds; + { + zval retval; + zval function_name; + + ZVAL_STRING(&function_name, "date_timestamp_get"); + + if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1, + datetime) == FAILURE || + !Convert_PhpToUpb(&retval, ×tamp_seconds, UPB_TYPE_INT64, NULL, + NULL)) { + zend_error(E_ERROR, "Cannot get timestamp from DateTime."); + return; + } + + zval_dtor(&retval); + zval_dtor(&function_name); + } + + upb_msgval timestamp_nanos; + { + zval retval; + zval function_name; + zval format_string; + + ZVAL_STRING(&function_name, "date_format"); + ZVAL_STRING(&format_string, "u"); + + zval params[2] = { + *datetime, + format_string, + }; + + if (call_user_function(EG(function_table), NULL, &function_name, &retval, 2, + params) == FAILURE || + !Convert_PhpToUpb(&retval, ×tamp_nanos, UPB_TYPE_INT32, NULL, + NULL)) { + zend_error(E_ERROR, "Cannot format DateTime."); + return; + } + + timestamp_nanos.int32_val *= 1000; + + zval_dtor(&retval); + zval_dtor(&function_name); + zval_dtor(&format_string); + } + + Message_setval(intern, "seconds", timestamp_seconds); + Message_setval(intern, "nanos", timestamp_nanos); + + RETURN_NULL(); +} + +PHP_METHOD(google_protobuf_Timestamp, toDateTime) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_msgval seconds = Message_getval(intern, "seconds"); + upb_msgval nanos = Message_getval(intern, "nanos"); + + // Get formatted time string. + char formatted_time[32]; + snprintf(formatted_time, sizeof(formatted_time), "%" PRId64 ".%06" PRId32, + seconds.int64_val, nanos.int32_val / 1000); + + // Create Datetime object. + zval datetime; + zval function_name; + zval format_string; + zval formatted_time_php; + + ZVAL_STRING(&function_name, "date_create_from_format"); + ZVAL_STRING(&format_string, "U.u"); + ZVAL_STRING(&formatted_time_php, formatted_time); + + zval params[2] = { + format_string, + formatted_time_php, + }; + + if (call_user_function(EG(function_table), NULL, &function_name, &datetime, 2, + params) == FAILURE) { + zend_error(E_ERROR, "Cannot create DateTime."); + return; + } + + zval_dtor(&function_name); + zval_dtor(&format_string); + zval_dtor(&formatted_time_php); + + ZVAL_OBJ(return_value, Z_OBJ(datetime)); +} #include "wkt.inc"
diff --git a/php/ext/google/protobuf/wkt.inc b/php/ext/google/protobuf/wkt.inc index c7a469f..29a6e51 100644 --- a/php/ext/google/protobuf/wkt.inc +++ b/php/ext/google/protobuf/wkt.inc
@@ -110,6 +110,8 @@ PHP_ME(google_protobuf_Timestamp, setSeconds, NULL, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Timestamp, getNanos, NULL, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Timestamp, setNanos, NULL, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, fromDateTime, NULL, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, toDateTime, NULL, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -724,6 +726,8 @@ PHP_ME(google_protobuf_Any, setTypeUrl, NULL, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Any, getValue, NULL, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Any, setValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Any, is, NULL, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Any, pack, NULL, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Any, unpack, NULL, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -1979,6 +1983,174 @@ zend_do_inheritance(google_protobuf_Field_ce, message_ce); } +/* google_protobuf_Field_Kind */ + +zend_class_entry* google_protobuf_Field_Kind_ce; + +PHP_METHOD(google_protobuf_Field_Kind, name) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Kind"); + const char *name; + zend_long value; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == + FAILURE) { + return; + } + name = upb_enumdef_iton(e, value); + if (!name) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Field\\Kind has no name " + "defined for value " ZEND_LONG_FMT ".", + value); + return; + } + RETURN_STRING(name); +} + +PHP_METHOD(google_protobuf_Field_Kind, value) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Kind"); + char *name = NULL; + size_t name_len; + int32_t num; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, + &name_len) == FAILURE) { + return; + } + if (!upb_enumdef_ntoi(e, name, name_len, &num)) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Field\\Kind has no value " + "defined for name %s.", + name); + return; + } + RETURN_LONG(num); +} + +static zend_function_entry google_protobuf_Field_Kind_phpmethods[] = { + PHP_ME(google_protobuf_Field_Kind, name, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(google_protobuf_Field_Kind, value, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void google_protobuf_Field_Kind_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Field\\Kind", + google_protobuf_Field_Kind_phpmethods); + + google_protobuf_Field_Kind_ce = zend_register_internal_class(&tmp_ce); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_UNKNOWN", + strlen("TYPE_UNKNOWN"), 0); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_DOUBLE", + strlen("TYPE_DOUBLE"), 1); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_FLOAT", + strlen("TYPE_FLOAT"), 2); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_INT64", + strlen("TYPE_INT64"), 3); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_UINT64", + strlen("TYPE_UINT64"), 4); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_INT32", + strlen("TYPE_INT32"), 5); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_FIXED64", + strlen("TYPE_FIXED64"), 6); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_FIXED32", + strlen("TYPE_FIXED32"), 7); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_BOOL", + strlen("TYPE_BOOL"), 8); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_STRING", + strlen("TYPE_STRING"), 9); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_GROUP", + strlen("TYPE_GROUP"), 10); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_MESSAGE", + strlen("TYPE_MESSAGE"), 11); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_BYTES", + strlen("TYPE_BYTES"), 12); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_UINT32", + strlen("TYPE_UINT32"), 13); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_ENUM", + strlen("TYPE_ENUM"), 14); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SFIXED32", + strlen("TYPE_SFIXED32"), 15); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SFIXED64", + strlen("TYPE_SFIXED64"), 16); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SINT32", + strlen("TYPE_SINT32"), 17); + zend_declare_class_constant_long(google_protobuf_Field_Kind_ce, "TYPE_SINT64", + strlen("TYPE_SINT64"), 18); +} + +/* google_protobuf_Field_Cardinality */ + +zend_class_entry* google_protobuf_Field_Cardinality_ce; + +PHP_METHOD(google_protobuf_Field_Cardinality, name) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Cardinality"); + const char *name; + zend_long value; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == + FAILURE) { + return; + } + name = upb_enumdef_iton(e, value); + if (!name) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Field\\Cardinality has no name " + "defined for value " ZEND_LONG_FMT ".", + value); + return; + } + RETURN_STRING(name); +} + +PHP_METHOD(google_protobuf_Field_Cardinality, value) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Field.Cardinality"); + char *name = NULL; + size_t name_len; + int32_t num; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, + &name_len) == FAILURE) { + return; + } + if (!upb_enumdef_ntoi(e, name, name_len, &num)) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Field\\Cardinality has no value " + "defined for name %s.", + name); + return; + } + RETURN_LONG(num); +} + +static zend_function_entry google_protobuf_Field_Cardinality_phpmethods[] = { + PHP_ME(google_protobuf_Field_Cardinality, name, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(google_protobuf_Field_Cardinality, value, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void google_protobuf_Field_Cardinality_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Field\\Cardinality", + google_protobuf_Field_Cardinality_phpmethods); + + google_protobuf_Field_Cardinality_ce = zend_register_internal_class(&tmp_ce); + zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_UNKNOWN", + strlen("CARDINALITY_UNKNOWN"), 0); + zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_OPTIONAL", + strlen("CARDINALITY_OPTIONAL"), 1); + zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_REQUIRED", + strlen("CARDINALITY_REQUIRED"), 2); + zend_declare_class_constant_long(google_protobuf_Field_Cardinality_ce, "CARDINALITY_REPEATED", + strlen("CARDINALITY_REPEATED"), 3); +} + /* google_protobuf_Enum */ zend_class_entry* google_protobuf_Enum_ce; @@ -2297,6 +2469,71 @@ zend_do_inheritance(google_protobuf_Option_ce, message_ce); } +/* google_protobuf_Syntax */ + +zend_class_entry* google_protobuf_Syntax_ce; + +PHP_METHOD(google_protobuf_Syntax, name) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Syntax"); + const char *name; + zend_long value; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == + FAILURE) { + return; + } + name = upb_enumdef_iton(e, value); + if (!name) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Syntax has no name " + "defined for value " ZEND_LONG_FMT ".", + value); + return; + } + RETURN_STRING(name); +} + +PHP_METHOD(google_protobuf_Syntax, value) { + google_protobuf_type_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.Syntax"); + char *name = NULL; + size_t name_len; + int32_t num; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, + &name_len) == FAILURE) { + return; + } + if (!upb_enumdef_ntoi(e, name, name_len, &num)) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\Syntax has no value " + "defined for name %s.", + name); + return; + } + RETURN_LONG(num); +} + +static zend_function_entry google_protobuf_Syntax_phpmethods[] = { + PHP_ME(google_protobuf_Syntax, name, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(google_protobuf_Syntax, value, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void google_protobuf_Syntax_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Syntax", + google_protobuf_Syntax_phpmethods); + + google_protobuf_Syntax_ce = zend_register_internal_class(&tmp_ce); + zend_declare_class_constant_long(google_protobuf_Syntax_ce, "SYNTAX_PROTO2", + strlen("SYNTAX_PROTO2"), 0); + zend_declare_class_constant_long(google_protobuf_Syntax_ce, "SYNTAX_PROTO3", + strlen("SYNTAX_PROTO3"), 1); +} + /* google/protobuf/struct.proto */ zend_class_entry* GPBMetadata_Google_Protobuf_Struct_ce; @@ -2619,6 +2856,13 @@ RETURN_ZVAL(getThis(), 1, 0); } +static PHP_METHOD(google_protobuf_Value, getKind) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_oneofdef *oneof = upb_msgdef_ntooz(intern->desc->msgdef, + "kind"); + const upb_fielddef *field = upb_msg_whichoneof(intern->msg, oneof); + RETURN_STRING(field ? upb_fielddef_name(field) : ""); +} static zend_function_entry google_protobuf_Value_phpmethods[] = { PHP_ME(google_protobuf_Value, __construct, NULL, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Value, getNullValue, NULL, ZEND_ACC_PUBLIC) @@ -2633,6 +2877,7 @@ PHP_ME(google_protobuf_Value, setStructValue, NULL, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Value, getListValue, NULL, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Value, setListValue, NULL, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Value, getKind, NULL, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -2698,6 +2943,69 @@ zend_do_inheritance(google_protobuf_ListValue_ce, message_ce); } +/* google_protobuf_NullValue */ + +zend_class_entry* google_protobuf_NullValue_ce; + +PHP_METHOD(google_protobuf_NullValue, name) { + google_protobuf_struct_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.NullValue"); + const char *name; + zend_long value; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == + FAILURE) { + return; + } + name = upb_enumdef_iton(e, value); + if (!name) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\NullValue has no name " + "defined for value " ZEND_LONG_FMT ".", + value); + return; + } + RETURN_STRING(name); +} + +PHP_METHOD(google_protobuf_NullValue, value) { + google_protobuf_struct_proto_AddDescriptor(); + const upb_symtab *symtab = DescriptorPool_GetSymbolTable(); + const upb_enumdef *e = upb_symtab_lookupenum(symtab, "google.protobuf.NullValue"); + char *name = NULL; + size_t name_len; + int32_t num; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, + &name_len) == FAILURE) { + return; + } + if (!upb_enumdef_ntoi(e, name, name_len, &num)) { + zend_throw_exception_ex(NULL, 0, + "Google\\Protobuf\\NullValue has no value " + "defined for name %s.", + name); + return; + } + RETURN_LONG(num); +} + +static zend_function_entry google_protobuf_NullValue_phpmethods[] = { + PHP_ME(google_protobuf_NullValue, name, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(google_protobuf_NullValue, value, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void google_protobuf_NullValue_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\NullValue", + google_protobuf_NullValue_phpmethods); + + google_protobuf_NullValue_ce = zend_register_internal_class(&tmp_ce); + zend_declare_class_constant_long(google_protobuf_NullValue_ce, "NULL_VALUE", + strlen("NULL_VALUE"), 0); +} + /* google/protobuf/source_context.proto */ zend_class_entry* GPBMetadata_Google_Protobuf_SourceContext_ce; @@ -2905,14 +3213,18 @@ GPBMetadata_Google_Protobuf_Type_ModuleInit(); google_protobuf_Type_ModuleInit(); google_protobuf_Field_ModuleInit(); + google_protobuf_Field_Kind_ModuleInit(); + google_protobuf_Field_Cardinality_ModuleInit(); google_protobuf_Enum_ModuleInit(); google_protobuf_EnumValue_ModuleInit(); google_protobuf_Option_ModuleInit(); + google_protobuf_Syntax_ModuleInit(); GPBMetadata_Google_Protobuf_Struct_ModuleInit(); google_protobuf_Struct_ModuleInit(); google_protobuf_Struct_FieldsEntry_ModuleInit(); google_protobuf_Value_ModuleInit(); google_protobuf_ListValue_ModuleInit(); + google_protobuf_NullValue_ModuleInit(); GPBMetadata_Google_Protobuf_SourceContext_ModuleInit(); google_protobuf_SourceContext_ModuleInit(); GPBMetadata_Google_Protobuf_FieldMask_ModuleInit();
diff --git a/php/generate_descriptor_protos.sh b/php/generate_descriptor_protos.sh index f636cc0..fc2ed80 100755 --- a/php/generate_descriptor_protos.sh +++ b/php/generate_descriptor_protos.sh
@@ -13,4 +13,15 @@ pushd src ./protoc --php_out=internal:../php/src google/protobuf/descriptor.proto +./protoc --php_out=internal_generate_c_wkt:src \ + google/protobuf/any.proto \ + google/protobuf/api.proto \ + google/protobuf/duration.proto \ + google/protobuf/empty.proto \ + google/protobuf/field_mask.proto \ + google/protobuf/source_context.proto \ + google/protobuf/struct.proto \ + google/protobuf/type.proto \ + google/protobuf/timestamp.proto \ + google/protobuf/wrappers.proto popd
diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 9b518f5..8560979 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc
@@ -1815,6 +1815,91 @@ return c_name; } +void GenerateCEnum(const EnumDescriptor* desc, io::Printer* printer) { + std::string c_name = desc->full_name(); + c_name = StringReplace(c_name, ".", "_", true); + std::string php_name = FullClassName(desc, Options()); + php_name = StringReplace(php_name, "\\", "\\\\", true); + printer->Print( + "/* $c_name$ */\n" + "\n" + "zend_class_entry* $c_name$_ce;\n" + "\n" + "PHP_METHOD($c_name$, name) {\n" + " $file_c_name$_AddDescriptor();\n" + " const upb_symtab *symtab = DescriptorPool_GetSymbolTable();\n" + " const upb_enumdef *e = upb_symtab_lookupenum(symtab, \"$name$\");\n" + " const char *name;\n" + " zend_long value;\n" + " if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, \"l\", &value) ==\n" + " FAILURE) {\n" + " return;\n" + " }\n" + " name = upb_enumdef_iton(e, value);\n" + " if (!name) {\n" + " zend_throw_exception_ex(NULL, 0,\n" + " \"$php_name$ has no name \"\n" + " \"defined for value \" ZEND_LONG_FMT \".\",\n" + " value);\n" + " return;\n" + " }\n" + " RETURN_STRING(name);\n" + "}\n" + "\n" + "PHP_METHOD($c_name$, value) {\n" + " $file_c_name$_AddDescriptor();\n" + " const upb_symtab *symtab = DescriptorPool_GetSymbolTable();\n" + " const upb_enumdef *e = upb_symtab_lookupenum(symtab, \"$name$\");\n" + " char *name = NULL;\n" + " size_t name_len;\n" + " int32_t num;\n" + " if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, \"s\", &name,\n" + " &name_len) == FAILURE) {\n" + " return;\n" + " }\n" + " if (!upb_enumdef_ntoi(e, name, name_len, &num)) {\n" + " zend_throw_exception_ex(NULL, 0,\n" + " \"$php_name$ has no value \"\n" + " \"defined for name %s.\",\n" + " name);\n" + " return;\n" + " }\n" + " RETURN_LONG(num);\n" + "}\n" + "\n" + "static zend_function_entry $c_name$_phpmethods[] = {\n" + " PHP_ME($c_name$, name, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n" + " PHP_ME($c_name$, value, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n" + " ZEND_FE_END\n" + "};\n" + "\n" + "static void $c_name$_ModuleInit() {\n" + " zend_class_entry tmp_ce;\n" + "\n" + " INIT_CLASS_ENTRY(tmp_ce, \"$php_name$\",\n" + " $c_name$_phpmethods);\n" + "\n" + " $c_name$_ce = zend_register_internal_class(&tmp_ce);\n", + "name", desc->full_name(), + "file_c_name", FilenameCName(desc->file()), + "c_name", c_name, + "php_name", php_name); + + for (int i = 0; i < desc->value_count(); i++) { + const EnumValueDescriptor* value = desc->value(i); + printer->Print( + " zend_declare_class_constant_long($c_name$_ce, \"$name$\",\n" + " strlen(\"$name$\"), $num$);\n", + "c_name", c_name, + "name", value->name(), + "num", std::to_string(value->number())); + } + + printer->Print( + "}\n" + "\n"); +} + void GenerateCMessage(const Descriptor* message, io::Printer* printer) { std::string c_name = message->full_name(); c_name = StringReplace(c_name, ".", "_", true); @@ -1863,6 +1948,21 @@ "camel_name", UnderscoresToCamelCase(field->name(), true)); } + for (int i = 0; i < message->real_oneof_decl_count(); i++) { + auto oneof = message->oneof_decl(i); + printer->Print( + "static PHP_METHOD($c_name$, get$camel_name$) {\n" + " Message* intern = (Message*)Z_OBJ_P(getThis());\n" + " const upb_oneofdef *oneof = upb_msgdef_ntooz(intern->desc->msgdef,\n" + " \"$name$\");\n" + " const upb_fielddef *field = upb_msg_whichoneof(intern->msg, oneof);\n" + " RETURN_STRING(field ? upb_fielddef_name(field) : \"\");\n" + "}\n", + "c_name", c_name, + "name", oneof->name(), + "camel_name", UnderscoresToCamelCase(oneof->name(), true)); + } + printer->Print( "static zend_function_entry $c_name$_phpmethods[] = {\n" " PHP_ME($c_name$, __construct, NULL, ZEND_ACC_PUBLIC)\n", @@ -1877,12 +1977,33 @@ "camel_name", UnderscoresToCamelCase(field->name(), true)); } - if (message->well_known_type() == Descriptor::WELLKNOWNTYPE_ANY) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { + auto oneof = message->oneof_decl(i); printer->Print( - " PHP_ME($c_name$, unpack, NULL, ZEND_ACC_PUBLIC)\n", - "c_name", c_name); + " PHP_ME($c_name$, get$camel_name$, NULL, ZEND_ACC_PUBLIC)\n", + "c_name", c_name, + "camel_name", UnderscoresToCamelCase(oneof->name(), true)); } + // Extra hand-written functions added to the well-known types. + switch (message->well_known_type()) { + case Descriptor::WELLKNOWNTYPE_ANY: + printer->Print( + " PHP_ME($c_name$, is, NULL, ZEND_ACC_PUBLIC)\n" + " PHP_ME($c_name$, pack, NULL, ZEND_ACC_PUBLIC)\n" + " PHP_ME($c_name$, unpack, NULL, ZEND_ACC_PUBLIC)\n", + "c_name", c_name); + break; + case Descriptor::WELLKNOWNTYPE_TIMESTAMP: + printer->Print( + " PHP_ME($c_name$, fromDateTime, NULL, ZEND_ACC_PUBLIC)\n" + " PHP_ME($c_name$, toDateTime, NULL, ZEND_ACC_PUBLIC)\n", + "c_name", c_name); + break; + default: + break; + } + printer->Print( " ZEND_FE_END\n" "};\n" @@ -1905,6 +2026,18 @@ for (int i = 0; i < message->nested_type_count(); i++) { GenerateCMessage(message->nested_type(i), printer); } + for (int i = 0; i < message->enum_type_count(); i++) { + GenerateCEnum(message->enum_type(i), printer); + } +} + +void GenerateEnumCInit(const EnumDescriptor* desc, io::Printer* printer) { + std::string c_name = desc->full_name(); + c_name = StringReplace(c_name, ".", "_", true); + + printer->Print( + " $c_name$_ModuleInit();\n", + "c_name", c_name); } void GenerateCInit(const Descriptor* message, io::Printer* printer) { @@ -1918,6 +2051,9 @@ for (int i = 0; i < message->nested_type_count(); i++) { GenerateCInit(message->nested_type(i), printer); } + for (int i = 0; i < message->enum_type_count(); i++) { + GenerateEnumCInit(message->enum_type(i), printer); + } } void GenerateCWellKnownTypes(const std::vector<const FileDescriptor*>& files, @@ -2011,6 +2147,9 @@ for (int i = 0; i < file->message_type_count(); i++) { GenerateCMessage(file->message_type(i), &printer); } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateCEnum(file->enum_type(i), &printer); + } } printer.Print( @@ -2027,6 +2166,9 @@ for (int i = 0; i < file->message_type_count(); i++) { GenerateCInit(file->message_type(i), &printer); } + for (int i = 0; i < file->enum_type_count(); i++) { + GenerateEnumCInit(file->enum_type(i), &printer); + } } printer.Print(