diff options
Diffstat (limited to 'php/ext/google/protobuf/def.c')
-rw-r--r-- | php/ext/google/protobuf/def.c | 117 |
1 files changed, 62 insertions, 55 deletions
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c index db6aec701..b14f59164 100644 --- a/php/ext/google/protobuf/def.c +++ b/php/ext/google/protobuf/def.c @@ -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) { |