Explorar o código

Change array to map for reserved names in c extension

Bo Yang %!s(int64=8) %!d(string=hai) anos
pai
achega
ddb9ef9cc3

+ 1 - 24
php/ext/google/protobuf/def.c

@@ -30,24 +30,6 @@
 
 #include "protobuf.h"
 
-const char *const kReservedNames[] = {
-    "abstract",   "and",        "array",        "as",           "break",
-    "callable",   "case",       "catch",        "class",        "clone",
-    "const",      "continue",   "declare",      "default",      "die",
-    "do",         "echo",       "else",         "elseif",       "empty",
-    "enddeclare", "endfor",     "endforeach",   "endif",        "endswitch",
-    "endwhile",   "eval",       "exit",         "extends",      "final",
-    "for",        "foreach",    "function",     "global",       "goto",
-    "if",         "implements", "include",      "include_once", "instanceof",
-    "insteadof",  "interface",  "isset",        "list",         "namespace",
-    "new",        "or",         "print",        "private",      "protected",
-    "public",     "require",    "require_once", "return",       "static",
-    "switch",     "throw",      "trait",        "try",          "unset",
-    "use",        "var",        "while",        "xor",          "int",
-    "float",      "bool",       "string",       "true",         "false",
-    "null",       "void",       "iterable"};
-const int kReservedNamesSize = 73;
-
 // Forward declare.
 static void descriptor_init_c_instance(Descriptor* intern TSRMLS_DC);
 static void descriptor_free_c(Descriptor* object TSRMLS_DC);
@@ -797,12 +779,7 @@ static const char *classname_prefix(const char *classname,
   }
   lower[i] = 0;
 
-  for (i = 0; i < kReservedNamesSize; i++) {
-    if (strcmp(kReservedNames[i], lower) == 0) {
-      is_reserved = true;
-      break;
-    }
-  }
+  is_reserved = is_reserved_name(lower);
   FREE(lower);
 
   if (is_reserved) {

+ 43 - 0
php/ext/google/protobuf/protobuf.c

@@ -46,6 +46,7 @@ static HashTable* upb_def_to_php_obj_map;
 // Global map from message/enum's php class entry to corresponding wrapper
 // Descriptor/EnumDescriptor instances.
 static HashTable* ce_to_php_obj_map;
+static HashTable* reserved_names;
 
 // -----------------------------------------------------------------------------
 // Global maps.
@@ -110,6 +111,36 @@ bool class_added(const void* ce) {
   return exist_in_table(ce_to_php_obj_map, ce);
 }
 
+// -----------------------------------------------------------------------------
+// Reserved Name.
+// -----------------------------------------------------------------------------
+
+// Although we already have kReservedNames, we still add them to hash table to
+// speed up look up.
+const char *const kReservedNames[] = {
+    "abstract",   "and",        "array",        "as",           "break",
+    "callable",   "case",       "catch",        "class",        "clone",
+    "const",      "continue",   "declare",      "default",      "die",
+    "do",         "echo",       "else",         "elseif",       "empty",
+    "enddeclare", "endfor",     "endforeach",   "endif",        "endswitch",
+    "endwhile",   "eval",       "exit",         "extends",      "final",
+    "for",        "foreach",    "function",     "global",       "goto",
+    "if",         "implements", "include",      "include_once", "instanceof",
+    "insteadof",  "interface",  "isset",        "list",         "namespace",
+    "new",        "or",         "print",        "private",      "protected",
+    "public",     "require",    "require_once", "return",       "static",
+    "switch",     "throw",      "trait",        "try",          "unset",
+    "use",        "var",        "while",        "xor",          "int",
+    "float",      "bool",       "string",       "true",         "false",
+    "null",       "void",       "iterable"};
+const int kReservedNamesSize = 73;
+
+bool is_reserved_name(const char* name) {
+  void** value;
+  return (php_proto_zend_hash_find(reserved_names, name, strlen(name),
+                                   (void**)&value) == SUCCESS);
+}
+
 // -----------------------------------------------------------------------------
 // Utilities.
 // -----------------------------------------------------------------------------
@@ -157,12 +188,21 @@ static void php_proto_hashtable_descriptor_release(zval* value) {
 #endif
 
 static PHP_RINIT_FUNCTION(protobuf) {
+  int i = 0;
+
   ALLOC_HASHTABLE(upb_def_to_php_obj_map);
   zend_hash_init(upb_def_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
 
   ALLOC_HASHTABLE(ce_to_php_obj_map);
   zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
 
+  ALLOC_HASHTABLE(reserved_names);
+  zend_hash_init(reserved_names, 16, NULL, NULL, 0);
+  for (i = 0; i < kReservedNamesSize; i++) {
+    php_proto_zend_hash_update(reserved_names, kReservedNames[i],
+                               strlen(kReservedNames[i]));
+  }
+
   generated_pool = NULL;
   generated_pool_php = NULL;
   internal_generated_pool_php = NULL;
@@ -177,6 +217,9 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) {
   zend_hash_destroy(ce_to_php_obj_map);
   FREE_HASHTABLE(ce_to_php_obj_map);
 
+  zend_hash_destroy(reserved_names);
+  FREE_HASHTABLE(reserved_names);
+
 #if PHP_MAJOR_VERSION < 7
   if (generated_pool_php != NULL) {
     zval_dtor(generated_pool_php);

+ 25 - 0
php/ext/google/protobuf/protobuf.h

@@ -77,12 +77,18 @@
 #define php_proto_zend_hash_index_update_zval(ht, h, pData) \
   zend_hash_index_update(ht, h, &(pData), sizeof(void*), NULL)
 
+#define php_proto_zend_hash_update(ht, key, key_len) \
+  zend_hash_update(ht, key, key_len, 0, 0, NULL)
+
 #define php_proto_zend_hash_index_update_mem(ht, h, pData, nDataSize, pDest) \
   zend_hash_index_update(ht, h, pData, nDataSize, pDest)
 
 #define php_proto_zend_hash_index_find_zval(ht, h, pDest) \
   zend_hash_index_find(ht, h, pDest)
 
+#define php_proto_zend_hash_find(ht, key, key_len, pDest) \
+  zend_hash_find(ht, key, key_len, pDest)
+
 #define php_proto_zend_hash_index_find_mem(ht, h, pDest) \
   zend_hash_index_find(ht, h, pDest)
 
@@ -234,6 +240,15 @@ static inline int php_proto_zend_hash_index_update_zval(HashTable* ht, ulong h,
   return result != NULL ? SUCCESS : FAILURE;
 }
 
+static inline int php_proto_zend_hash_update(HashTable* ht, const char* key,
+                                             size_t key_len) {
+  void* result = NULL;
+  zval temp;
+  ZVAL_LONG(&temp, 0);
+  result = zend_hash_str_update(ht, key, key_len, &temp);
+  return result != NULL ? SUCCESS : FAILURE;
+}
+
 static inline int php_proto_zend_hash_index_update_mem(HashTable* ht, ulong h,
                                                    void* pData, uint nDataSize,
                                                    void** pDest) {
@@ -250,6 +265,13 @@ static inline int php_proto_zend_hash_index_find_zval(const HashTable* ht,
   return result != NULL ? SUCCESS : FAILURE;
 }
 
+static inline int php_proto_zend_hash_find(const HashTable* ht, const char* key,
+                                           size_t key_len, void** pDest) {
+  void* result = NULL;
+  result = zend_hash_str_find(ht, key, key_len);
+  return result != NULL ? SUCCESS : FAILURE;
+}
+
 static inline int php_proto_zend_hash_index_find_mem(const HashTable* ht,
                                                      ulong h, void** pDest) {
   void* result = NULL;
@@ -910,4 +932,7 @@ const zend_class_entry* field_type_class(
                       .bucket.obj.object))
 #endif
 
+// Reserved name
+bool is_reserved_name(const char* name);
+
 #endif  // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__