aboutsummaryrefslogtreecommitdiffhomepage
path: root/php/ext/google/protobuf/def.c
diff options
context:
space:
mode:
Diffstat (limited to 'php/ext/google/protobuf/def.c')
-rw-r--r--php/ext/google/protobuf/def.c256
1 files changed, 167 insertions, 89 deletions
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c
index 13f7cdd6..fa33830b 100644
--- a/php/ext/google/protobuf/def.c
+++ b/php/ext/google/protobuf/def.c
@@ -249,9 +249,11 @@ PHP_METHOD(Descriptor, getField) {
MAKE_STD_ZVAL(field_hashtable_value);
ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object(
field_descriptor_type TSRMLS_CC));
+ Z_DELREF_P(field_hashtable_value);
#else
field_hashtable_value =
field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC);
+ --GC_REFCOUNT(field_hashtable_value);
#endif
FieldDescriptor *field_php =
UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value);
@@ -716,105 +718,187 @@ PHP_METHOD(InternalDescriptorPool, getGeneratedPool) {
#endif
}
-static void classname_no_prefix(const char *fullname, const char *package_name,
- char *class_name) {
- size_t i = 0, j;
- bool first_char = true, is_reserved = false;
- size_t pkg_name_len = package_name == NULL ? 0 : strlen(package_name);
- size_t message_name_start = package_name == NULL ? 0 : pkg_name_len + 1;
- size_t message_len = (strlen(fullname) - message_name_start);
+static size_t classname_len_max(const char *fullname,
+ const char *package,
+ const char *php_namespace,
+ const char *prefix) {
+ size_t fullname_len = strlen(fullname);
+ size_t package_len = 0;
+ size_t prefix_len = 0;
+ size_t namespace_len = 0;
+ size_t length = fullname_len;
+ int i, segment, classname_start = 0;
+
+ if (package != NULL) {
+ package_len = strlen(package);
+ }
+ if (prefix != NULL) {
+ prefix_len = strlen(prefix);
+ }
+ if (php_namespace != NULL) {
+ namespace_len = strlen(php_namespace);
+ }
- // Submessage is concatenated with its containing messages by '_'.
- for (j = message_name_start; j < message_name_start + message_len; j++) {
- if (fullname[j] == '.') {
- class_name[i++] = '_';
- } else {
- class_name[i++] = fullname[j];
+ // Process package
+ if (package_len > 0) {
+ segment = 1;
+ for (i = 0; i < package_len; i++) {
+ if (package[i] == '.') {
+ segment++;
+ }
}
- }
-}
+ // In case of reserved name in package.
+ length += 3 * segment;
-static const char *classname_prefix(const char *classname,
- const char *prefix_given,
- const char *package_name) {
- size_t i;
- bool is_reserved = false;
+ classname_start = package_len + 1;
+ }
- if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
- return prefix_given;
+ // Process class name
+ segment = 1;
+ for (i = classname_start; i < fullname_len; i++) {
+ if (fullname[i] == '.') {
+ segment++;
+ }
+ }
+ if (prefix_len == 0) {
+ length += 3 * segment;
+ } else {
+ length += prefix_len * segment;
}
- char* lower = ALLOC_N(char, strlen(classname) + 1);
- i = 0;
- while(classname[i]) {
- lower[i] = (char)tolower(classname[i]);
+ // The additional 2, one is for preceding '.' and the other is for trailing 0.
+ return length + namespace_len + 2;
+}
+
+static bool is_reserved(const char *segment, int length) {
+ bool result;
+ char* lower = ALLOC_N(char, length + 1);
+ memset(lower, 0, length + 1);
+ memcpy(lower, segment, length);
+ int i = 0;
+ while(lower[i]) {
+ lower[i] = (char)tolower(lower[i]);
i++;
}
- lower[i] = 0;
-
- is_reserved = is_reserved_name(lower);
+ lower[length] = 0;
+ result = is_reserved_name(lower);
FREE(lower);
+ return result;
+}
- if (is_reserved) {
- if (package_name != NULL && strcmp("google.protobuf", package_name) == 0) {
- return "GPB";
- } else {
- return "PB";
+static char* fill_prefix(const char *segment, int length,
+ const char *prefix_given,
+ const char *package_name, char *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;
+ } else {
+ if (is_reserved(segment, length)) {
+ if (package_name != NULL &&
+ strcmp("google.protobuf", package_name) == 0) {
+ memcpy(classname, "GPB", 3);
+ classname += 3;
+ } else {
+ memcpy(classname, "PB", 2);
+ classname += 2;
+ }
}
}
+ return classname;
+}
- return "";
+static char* fill_segment(const char *segment, int length,
+ char *classname, bool use_camel) {
+ memcpy(classname, segment, length);
+ if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
+ classname[0] += 'A' - 'a';
+ }
+ return classname + length;
}
-static void convert_to_class_name_inplace(const char *package,
- const char *namespace_given,
- const char *prefix, char *classname) {
- size_t prefix_len = prefix == NULL ? 0 : strlen(prefix);
- size_t classname_len = strlen(classname);
- int i = 0, j;
- bool first_char = true;
+static char* fill_namespace(const char *package, const char *namespace_given,
+ char *classname) {
+ if (namespace_given != NULL) {
+ size_t namespace_len = strlen(namespace_given);
+ memcpy(classname, namespace_given, namespace_len);
+ classname += namespace_len;
+ *classname = '\\';
+ classname++;
+ } else if (package != NULL) {
+ int i = 0, j, offset = 0;
+ size_t package_len = strlen(package);
+ while (i < package_len) {
+ j = i;
+ 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++;
+ i = j + 1;
+ }
+ }
+ return classname;
+}
- size_t package_len = package == NULL ? 0 : strlen(package);
- size_t namespace_given_len =
- namespace_given == NULL ? 0 : strlen(namespace_given);
- bool use_namespace_given = namespace_given != NULL;
- size_t namespace_len =
- use_namespace_given ? namespace_given_len : package_len;
+static char* fill_classname(const char *fullname,
+ const char *package,
+ const char *namespace_given,
+ const char *prefix, char *classname) {
+ 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);
+
+ int i = classname_start, j;
+ while (i < fullname_len) {
+ j = i;
+ while (j < fullname_len && fullname[j] != '.') {
+ j++;
+ }
+ classname = fill_segment(fullname + i, j - i, classname, false);
+ if (j != fullname_len) {
+ *classname = '_';
+ classname++;
+ }
+ i = j + 1;
+ }
+ return classname;
+}
- int offset = namespace_len != 0 ? 2 : 0;
+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);
+}
- for (j = 0; j < classname_len; j++) {
- classname[namespace_len + prefix_len + classname_len + offset - 1 - j] =
- classname[classname_len - j - 1];
- }
+static void classname_no_prefix(const char *fullname, const char *package_name,
+ char *class_name) {
+ size_t i = 0, j;
+ bool first_char = true, is_reserved = false;
+ size_t pkg_name_len = package_name == NULL ? 0 : strlen(package_name);
+ size_t message_name_start = package_name == NULL ? 0 : pkg_name_len + 1;
+ size_t message_len = (strlen(fullname) - message_name_start);
- if (namespace_len != 0) {
- classname[i++] = '\\';
- for (j = 0; j < namespace_len; j++) {
- if (use_namespace_given) {
- classname[i++] = namespace_given[j];
- continue;
- }
- // php packages are divided by '\'.
- if (package[j] == '.') {
- classname[i++] = '\\';
- first_char = true;
- } else if (first_char) {
- // PHP package uses camel case.
- if (package[j] < 'A' || package[j] > 'Z') {
- classname[i++] = package[j] + 'A' - 'a';
- } else {
- classname[i++] = package[j];
- }
- first_char = false;
- } else {
- classname[i++] = package[j];
- }
+ // Submessage is concatenated with its containing messages by '_'.
+ for (j = message_name_start; j < message_name_start + message_len; j++) {
+ if (fullname[j] == '.') {
+ class_name[i++] = '_';
+ } else {
+ class_name[i++] = fullname[j];
}
- classname[i++] = '\\';
}
-
- memcpy(classname + i, prefix, prefix_len);
}
void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
@@ -856,20 +940,14 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
* bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if \
* given message is google.protobuf.Empty.*/ \
const char *fullname = upb_##def_type_lower##_fullname(def_type_lower); \
+ 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 = strlen(fullname) + 5; \
- if (prefix_given != NULL) { \
- classname_len += strlen(prefix_given); \
- } \
- if (php_namespace != NULL) { \
- classname_len += strlen(php_namespace); \
- } \
+ size_t classname_len = classname_len_max(fullname, package, \
+ php_namespace, prefix_given); \
char *classname = ecalloc(sizeof(char), classname_len); \
- const char *package = upb_filedef_package(files[0]); \
- classname_no_prefix(fullname, package, classname); \
- const char *prefix = classname_prefix(classname, prefix_given, package); \
- convert_to_class_name_inplace(package, php_namespace, prefix, classname); \
+ fill_qualified_classname(fullname, package, php_namespace, \
+ prefix_given, classname); \
PHP_PROTO_CE_DECLARE pce; \
if (php_proto_zend_lookup_class(classname, strlen(classname), &pce) == \
FAILURE) { \