Unverified Commit 53a1d496 authored by Paul Yang's avatar Paul Yang Committed by GitHub

Allow internalAddGeneratedFile to depend on new nested message name (#5629)

Previously, internalAddGeneratedFile has to depend on old non-nested name for sub-messages.
This creates a hard dependency on old generated code for compatibility usage.
If user's code has custome error handler, the deprecation warning in the old generated code
will also be thrown (even though users haven't explicitly depended on the old message name).

To fix this problem, this change added an additional flag in the generated code to tell run
time that it's safe to use new message name. In this way, internalAddGeneratedFile can safely
depend on new name and don't trigger unnecessary deprecation warning.
parent dab6a7ea
......@@ -789,47 +789,44 @@ static bool is_reserved(const char *segment, int length) {
return result;
}
static char* fill_prefix(const char *segment, int length,
const char *prefix_given,
const char *package_name, char *classname) {
static void fill_prefix(const char *segment, int length,
const char *prefix_given,
const char *package_name,
stringsink *classname) {
size_t i;
if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
size_t prefix_len = strlen(prefix_given);
memcpy(classname, prefix_given, strlen(prefix_given));
classname += prefix_len;
stringsink_string(classname, NULL, prefix_given,
strlen(prefix_given), NULL);
} else {
if (is_reserved(segment, length)) {
if (package_name != NULL &&
strcmp("google.protobuf", package_name) == 0) {
memcpy(classname, "GPB", 3);
classname += 3;
stringsink_string(classname, NULL, "GPB", 3, NULL);
} else {
memcpy(classname, "PB", 2);
classname += 2;
stringsink_string(classname, NULL, "PB", 2, NULL);
}
}
}
return classname;
}
static char* fill_segment(const char *segment, int length,
char *classname, bool use_camel) {
memcpy(classname, segment, length);
static void fill_segment(const char *segment, int length,
stringsink *classname, bool use_camel) {
if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
classname[0] += 'A' - 'a';
char first = segment[0] + ('A' - 'a');
stringsink_string(classname, NULL, &first, 1, NULL);
stringsink_string(classname, NULL, segment + 1, length - 1, NULL);
} else {
stringsink_string(classname, NULL, segment, length, NULL);
}
return classname + length;
}
static char* fill_namespace(const char *package, const char *namespace_given,
char *classname) {
static void fill_namespace(const char *package, const char *namespace_given,
stringsink *classname) {
if (namespace_given != NULL) {
size_t namespace_len = strlen(namespace_given);
memcpy(classname, namespace_given, namespace_len);
classname += namespace_len;
*classname = '\\';
classname++;
stringsink_string(classname, NULL, namespace_given,
strlen(namespace_given), NULL);
stringsink_string(classname, NULL, "\\", 1, NULL);
} else if (package != NULL) {
int i = 0, j, offset = 0;
size_t package_len = strlen(package);
......@@ -838,29 +835,27 @@ static char* fill_namespace(const char *package, const char *namespace_given,
while (j < package_len && package[j] != '.') {
j++;
}
classname = fill_prefix(package + i, j - i, "", package, classname);
classname = fill_segment(package + i, j - i, classname, true);
classname[0] = '\\';
classname++;
fill_prefix(package + i, j - i, "", package, classname);
fill_segment(package + i, j - i, classname, true);
stringsink_string(classname, NULL, "\\", 1, NULL);
i = j + 1;
}
}
return classname;
}
static char* fill_classname(const char *fullname,
const char *package,
const char *namespace_given,
const char *prefix, char *classname) {
static void fill_classname(const char *fullname,
const char *package,
const char *namespace_given,
const char *prefix,
stringsink *classname,
bool use_nested_submsg) {
int classname_start = 0;
if (package != NULL) {
size_t package_len = strlen(package);
classname_start = package_len == 0 ? 0 : package_len + 1;
}
size_t fullname_len = strlen(fullname);
classname = fill_prefix(fullname + classname_start,
fullname_len - classname_start,
prefix, package, classname);
bool is_first_segment = true;
int i = classname_start, j;
while (i < fullname_len) {
......@@ -868,22 +863,31 @@ static char* fill_classname(const char *fullname,
while (j < fullname_len && fullname[j] != '.') {
j++;
}
classname = fill_segment(fullname + i, j - i, classname, false);
if (use_nested_submsg || is_first_segment && j == fullname_len) {
fill_prefix(fullname + i, j - i, prefix, package, classname);
}
is_first_segment = false;
fill_segment(fullname + i, j - i, classname, false);
if (j != fullname_len) {
*classname = '_';
classname++;
if (use_nested_submsg) {
stringsink_string(classname, NULL, "\\", 1, NULL);
} else {
stringsink_string(classname, NULL, "_", 1, NULL);
}
}
i = j + 1;
}
return classname;
}
static char* fill_qualified_classname(const char *fullname,
const char *package,
const char *namespace_given,
const char *prefix, char *classname) {
classname = fill_namespace(package, namespace_given, classname);
return fill_classname(fullname, package, namespace_given, prefix, classname);
static void fill_qualified_classname(const char *fullname,
const char *package,
const char *namespace_given,
const char *prefix,
stringsink *classname,
bool use_nested_submsg) {
fill_namespace(package, namespace_given, classname);
fill_classname(fullname, package, namespace_given, prefix,
classname, use_nested_submsg);
}
static void classname_no_prefix(const char *fullname, const char *package_name,
......@@ -905,7 +909,8 @@ static void classname_no_prefix(const char *fullname, const char *package_name,
}
void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
InternalDescriptorPool *pool TSRMLS_DC) {
InternalDescriptorPool *pool,
bool use_nested_submsg TSRMLS_DC) {
upb_filedef **files;
size_t i;
......@@ -946,16 +951,15 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
const char *package = upb_filedef_package(files[0]); \
const char *php_namespace = upb_filedef_phpnamespace(files[0]); \
const char *prefix_given = upb_filedef_phpprefix(files[0]); \
size_t classname_len = classname_len_max(fullname, package, \
php_namespace, prefix_given); \
char *classname = ecalloc(sizeof(char), classname_len); \
stringsink namesink; \
stringsink_init(&namesink); \
fill_qualified_classname(fullname, package, php_namespace, \
prefix_given, classname); \
prefix_given, &namesink, use_nested_submsg); \
PHP_PROTO_CE_DECLARE pce; \
if (php_proto_zend_lookup_class(classname, strlen(classname), &pce) == \
if (php_proto_zend_lookup_class(namesink.ptr, namesink.len, &pce) == \
FAILURE) { \
zend_error(E_ERROR, "Generated message class %s hasn't been defined", \
classname); \
namesink.ptr); \
return; \
} else { \
desc->klass = PHP_PROTO_CE_UNREF(pce); \
......@@ -963,7 +967,7 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
add_ce_obj(desc->klass, desc_php); \
add_proto_obj(upb_##def_type_lower##_fullname(desc->def_type_lower), \
desc_php); \
efree(classname); \
stringsink_uninit(&namesink); \
break; \
}
......@@ -993,15 +997,18 @@ PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
char *data = NULL;
PHP_PROTO_SIZE data_len;
upb_filedef **files;
zend_bool use_nested_submsg = false;
size_t i;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b",
&data, &data_len, &use_nested_submsg) ==
FAILURE) {
return;
}
InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis());
internal_add_generated_file(data, data_len, pool TSRMLS_CC);
internal_add_generated_file(data, data_len, pool,
use_nested_submsg TSRMLS_CC);
}
PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
......
......@@ -36,22 +36,14 @@
/* stringsink *****************************************************************/
typedef struct {
upb_byteshandler handler;
upb_bytessink sink;
char *ptr;
size_t len, size;
} stringsink;
static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
stringsink *sink = _sink;
sink->len = 0;
return sink;
}
static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
size_t len, const upb_bufhandle *handle) {
size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
size_t len, const upb_bufhandle *handle) {
stringsink *sink = _sink;
size_t new_size = sink->size;
......
......@@ -591,7 +591,8 @@ static void init_file_any(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_any = true;
}
......@@ -631,7 +632,8 @@ static void init_file_api(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_api = true;
}
......@@ -651,7 +653,8 @@ static void init_file_duration(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_duration = true;
}
......@@ -671,7 +674,8 @@ static void init_file_field_mask(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_field_mask = true;
}
......@@ -690,7 +694,8 @@ static void init_file_empty(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_empty = true;
}
......@@ -711,7 +716,8 @@ static void init_file_source_context(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_source_context = true;
}
......@@ -745,7 +751,8 @@ static void init_file_struct(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_struct = true;
}
......@@ -765,7 +772,8 @@ static void init_file_timestamp(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_timestamp = true;
}
......@@ -833,7 +841,8 @@ static void init_file_type(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_type = true;
}
......@@ -860,7 +869,8 @@ static void init_file_wrappers(TSRMLS_D) {
char* binary;
int binary_len;
hex_to_binary(generated_file, &binary, &binary_len);
internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
internal_add_generated_file(binary, binary_len,
generated_pool, true TSRMLS_CC);
FREE(binary);
is_inited_file_wrappers = true;
}
......
......@@ -770,7 +770,8 @@ PHP_METHOD(InternalDescriptorPool, getGeneratedPool);
PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile);
void internal_add_generated_file(const char* data, PHP_PROTO_SIZE data_len,
InternalDescriptorPool* pool TSRMLS_DC);
InternalDescriptorPool* pool,
bool use_nested_submsg TSRMLS_DC);
void init_generated_pool_once(TSRMLS_D);
// wrapper of generated pool
......@@ -1453,6 +1454,18 @@ const zend_class_entry* field_type_class(
const upb_fielddef* field PHP_PROTO_TSRMLS_DC);
void stringsink_uninit_opaque(void *sink);
typedef struct {
upb_byteshandler handler;
upb_bytessink sink;
char *ptr;
size_t len, size;
} stringsink;
void stringsink_init(stringsink *sink);
void stringsink_uninit(stringsink *sink);
size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
size_t len, const upb_bufhandle *handle);
// -----------------------------------------------------------------------------
// Utilities.
// -----------------------------------------------------------------------------
......
......@@ -1010,7 +1010,7 @@ void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor,
Outdent(printer);
printer->Print(
"));\n\n");
"), true);\n\n");
}
printer->Print(
"static::$is_initialized = true;\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment