|
@@ -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) {
|