Browse Source

add hash(Filename)

David Rose 16 years ago
parent
commit
1db044ca4e

+ 42 - 1
dtool/src/dtoolutil/filename.cxx

@@ -1030,7 +1030,11 @@ make_canonical() {
   }
 
   Filename cwd = ExecutionEnvironment::get_cwd();
-  return r_make_canonical(cwd);
+  if (!r_make_canonical(cwd)) {
+    return false;
+  }
+
+  return make_true_case();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2463,6 +2467,43 @@ make_dir() const {
   return (result == 0);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Filename::get_hash
+//       Access: Published
+//  Description: Returns a hash code that attempts to be mostly unique
+//               for different Filenames.
+////////////////////////////////////////////////////////////////////
+int Filename::
+get_hash() const {
+  static const int primes[] = {
+      2,    3,    5,    7,   11,   13,   17,   19,   23,   29,
+     31,   37,   41,   43,   47,   53,   59,   61,   67,   71,
+     73,   79,   83,   89,   97,  101,  103,  107,  109,  113,
+    127,  131,  137,  139,  149,  151,  157,  163,  167,  173,
+    179,  181,  191,  193,  197,  199,  211,  223,  227,  229,
+    233,  239,  241,  251,  257,  263,  269,  271,  277,  281,
+    283,  293,  307,  311,  313,  317,  331,  337,  347,  349,
+    353,  359,  367,  373,  379,  383,  389,  397,  401,  409,
+    419,  421,  431,  433,  439,  443,  449,  457,  461,  463,
+    467,  479,  487,  491,  499,  503,  509,  521,  523,  541,
+    547,  557,  563,  569,  571,  577,  587,  593,  599,  601,
+    607,  613,  617,  619,  631,  641,  643,  647,  653,  659,
+    661,  673,  677,  683,  691,  701,  709,  719,  727,  733,
+    739,  743,  751,  757,  761,  769,  773,  787,  797,  809,
+    811,  821,  823,  827,  829,  839,  853,  857,  859,  863,
+    877,  881,  883,  887,  907,  911,  919,  929,  937,  941,
+    947,  953,  967,  971,  977,  983,  991,  997
+  };
+  static const size_t num_primes = sizeof(primes) / sizeof(int);
+
+  int hash = 0;
+  for (size_t i = 0; i < _filename.size(); ++i) {
+    hash += (int)_filename[i] * primes[i % num_primes];
+  }
+
+  return hash;
+}
+
 
 ////////////////////////////////////////////////////////////////////
 //     Function: Filename::atomic_compare_and_exchange_contents

+ 1 - 0
dtool/src/dtoolutil/filename.h

@@ -205,6 +205,7 @@ PUBLISHED:
   INLINE bool operator < (const string &other) const;
   INLINE int compare_to(const Filename &other) const;
   INLINE bool __nonzero__() const;
+  int get_hash() const;
 
   INLINE void output(ostream &out) const;
 

+ 52 - 57
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -1502,10 +1502,28 @@ write_module_class(ostream &out,  Object *obj) {
       }
     }
 
-    if(HasAGetKeyFunction(obj->_itype)) 
-      {
+    string get_key = HasAGetKeyFunction(obj->_itype);
+    if (!get_key.empty()) {
+      out << "//////////////////\n";
+      out << "//  A LocalHash(getKey) Function for this type\n";
+      out << "//     " <<ClassName << "\n";
+      out << "//////////////////\n";
+      out << "static long  DTool_HashKey_"<<ClassName << "(PyObject * self)\n";
+      out << "{\n";
+      out << "    "<<cClassName  << " * local_this = NULL;\n";
+      out << "    DTOOL_Call_ExtractThisPointerForType(self,&Dtool_"<<  ClassName<<",(void **)&local_this);\n";
+      out << "    if(local_this == NULL)\n";
+      out << "    {\n";
+      out << "       PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n";
+      out << "       return -1;\n";
+      out << "    };\n";
+      out << "    return local_this->" << get_key << "();\n";
+      out << "}\n\n";
+      has_local_hash = true;
+    } else {
+      if(bases.size() == 0) {
         out << "//////////////////\n";
-        out << "//  A LocalHash(getKey) Function for this type\n";
+        out << "//  A LocalHash(This Pointer) Function for this type\n";
         out << "//     " <<ClassName << "\n";
         out << "//////////////////\n";
         out << "static long  DTool_HashKey_"<<ClassName << "(PyObject * self)\n";
@@ -1517,33 +1535,12 @@ write_module_class(ostream &out,  Object *obj) {
         out << "       PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n";
         out << "       return -1;\n";
         out << "    };\n";
-        out << "    return local_this->get_key();\n";
+        out << "    return (long)local_this;\n";
         out << "}\n\n";
         has_local_hash = true;
       }
-    else
-      {
-        if(bases.size() == 0)
-          {
-            out << "//////////////////\n";
-            out << "//  A LocalHash(This Pointer) Function for this type\n";
-            out << "//     " <<ClassName << "\n";
-            out << "//////////////////\n";
-            out << "static long  DTool_HashKey_"<<ClassName << "(PyObject * self)\n";
-            out << "{\n";
-            out << "    "<<cClassName  << " * local_this = NULL;\n";
-            out << "    DTOOL_Call_ExtractThisPointerForType(self,&Dtool_"<<  ClassName<<",(void **)&local_this);\n";
-            out << "    if(local_this == NULL)\n";
-            out << "    {\n";
-            out << "       PyErr_SetString(PyExc_AttributeError, \"C++ object is not yet constructed, or already destructed.\");\n";
-            out << "       return -1;\n";
-            out << "    };\n";
-            out << "    return (long)local_this;\n";
-            out << "}\n\n";
-            has_local_hash = true;
-          }
-      }
-
+    }
+    
     int need_repr = NeedsAReprFunction(obj->_itype);
     if(need_repr > 0)
       {
@@ -3383,44 +3380,42 @@ bool   InterfaceMakerPythonNative::DoesInheritFromIsClass( const CPPStructType *
 ////////////////////////////////////////////////////////////////////////////////////////////
 //  Function : HasAGetKeyFunction
 //
-// does the class have a supportable GetKey for hash usage..
+// does the class have a supportable get_key() or get_hash() to return
+// a usable Python hash?  Returns the name of the method, or empty
+// string if there is no suitable method.
 //////////////////////////////////////////////////////////////////////////////////////////
-bool InterfaceMakerPythonNative::HasAGetKeyFunction(const InterrogateType &itype_class)
-{
+string InterfaceMakerPythonNative::
+HasAGetKeyFunction(const InterrogateType &itype_class) {
   InterrogateDatabase *idb = InterrogateDatabase::get_ptr();
 
   int num_methods = itype_class.number_of_methods();
   int mi;
-  for (mi = 0; mi < num_methods; mi++) 
-  {
-      FunctionIndex func_index = itype_class.get_method(mi);
-      const InterrogateFunction &ifunc = idb->get_function(func_index);
-      if(ifunc.get_name() == "get_key") 
-      {
-          if (ifunc._instances != (InterrogateFunction::Instances *)NULL) 
-          {
-              InterrogateFunction::Instances::const_iterator ii;
-              for (ii = ifunc._instances->begin();ii != ifunc._instances->end();++ii) 
-              {
-                  CPPInstance *cppinst = (*ii).second;
-                  CPPFunctionType *cppfunc = cppinst->_type->as_function_type();
-
-                  if(cppfunc != NULL)
-                  {
-                      if(cppfunc->_parameters != NULL && cppfunc->_return_type != NULL && TypeManager::is_integer(cppfunc->_return_type))
-                      {
-                          if(cppfunc->_parameters->_parameters.size() == 0)
-                          {
-                              return true;
-                          }
-                      }
-                  }
-
-              }   
+  for (mi = 0; mi < num_methods; mi++) {
+    FunctionIndex func_index = itype_class.get_method(mi);
+    const InterrogateFunction &ifunc = idb->get_function(func_index);
+    if (ifunc.get_name() == "get_key" || ifunc.get_name() == "get_hash") {
+      if (ifunc._instances != (InterrogateFunction::Instances *)NULL) {
+        InterrogateFunction::Instances::const_iterator ii;
+        for (ii = ifunc._instances->begin();
+             ii != ifunc._instances->end();
+             ++ii) {
+          CPPInstance *cppinst = (*ii).second;
+          CPPFunctionType *cppfunc = cppinst->_type->as_function_type();
+          
+          if (cppfunc != NULL) {
+            if (cppfunc->_parameters != NULL &&
+                cppfunc->_return_type != NULL && 
+                TypeManager::is_integer(cppfunc->_return_type)) {
+              if (cppfunc->_parameters->_parameters.size() == 0) {
+                return ifunc.get_name();
+              }
+            }
           }
+        }   
       }
+    }
   }
-      return false;
+  return string();
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////

+ 1 - 1
dtool/src/interrogate/interfaceMakerPythonNative.h

@@ -130,7 +130,7 @@ public:
   bool   DoesInheritFromIsClass( const CPPStructType * inclass, const std::string &name);
   bool   IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); };
   void WriteReturnInstance(ostream &out, int indent_level, std::string &return_expr, std::string &ows_memory_flag,const std::string &class_name, CPPType *ctype, bool inplace, const std::string &const_flag);
-  bool HasAGetKeyFunction(const InterrogateType &itype_class);
+  string HasAGetKeyFunction(const InterrogateType &itype_class);
   bool HasAGetClassTypeFunction(const InterrogateType &itype_class);
   int NeedsAStrFunction(const InterrogateType &itype_class);
   int NeedsAReprFunction(const InterrogateType &itype_class);