Browse Source

*** empty log message ***

David Rose 25 years ago
parent
commit
c47d83286d

+ 3 - 0
direct/src/dcparse/dcparse.cxx

@@ -26,5 +26,8 @@ main(int argc, char *argv[]) {
     return (1);
     return (1);
   }
   }
 
 
+  long hash = file.get_hash();
+  cout << "File hash is " << hash << "\n";
+
   return (0);
   return (0);
 }
 }

+ 5 - 2
direct/src/dcparser/Sources.pp

@@ -12,10 +12,13 @@
 
 
   #define SOURCES \
   #define SOURCES \
     dcAtomicField.cxx dcAtomicField.h dcClass.cxx dcClass.h \
     dcAtomicField.cxx dcAtomicField.h dcClass.cxx dcClass.h \
-    dcField.cxx dcField.h dcFile.cxx dcFile.h dcLexer.lxx dcLexerDefs.h \
+    dcField.cxx dcField.h dcFile.cxx dcFile.h \
+    dcLexer.lxx dcLexerDefs.h \
     dcMolecularField.cxx dcMolecularField.h dcParser.yxx \
     dcMolecularField.cxx dcMolecularField.h dcParser.yxx \
     dcParserDefs.h dcSubatomicType.cxx dcSubatomicType.h dcbase.h \
     dcParserDefs.h dcSubatomicType.cxx dcSubatomicType.h dcbase.h \
-    dcindent.cxx dcindent.h
+    dcindent.cxx dcindent.h \
+    hashGenerator.cxx hashGenerator.h \
+    primeNumberGenerator.h primeNumberGenerator.cxx
 
 
   #define IGATESCAN all
   #define IGATESCAN all
 #end lib_target
 #end lib_target

+ 21 - 0
direct/src/dcparser/dcAtomicField.cxx

@@ -4,6 +4,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "dcAtomicField.h"
 #include "dcAtomicField.h"
+#include "hashGenerator.h"
 #include "dcindent.h"
 #include "dcindent.h"
 
 
 
 
@@ -213,3 +214,23 @@ write(ostream &out, int indent_level) const {
 
 
   out << ";  // field " << _number << "\n";
   out << ";  // field " << _number << "\n";
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::generate_hash
+//       Access: Public, Virtual
+//  Description: Accumulates the properties of this field into the
+//               hash.
+////////////////////////////////////////////////////////////////////
+void DCAtomicField::
+generate_hash(HashGenerator &hash) const {
+  DCField::generate_hash(hash);
+
+  hash.add_int(_elements.size());
+  Elements::const_iterator ei;
+  for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
+    const ElementType &element = (*ei);
+    hash.add_int(element._type);
+    hash.add_int(element._divisor);
+  }
+  hash.add_int(_flags);
+}

+ 1 - 0
direct/src/dcparser/dcAtomicField.h

@@ -39,6 +39,7 @@ PUBLISHED:
 public:
 public:
   DCAtomicField();
   DCAtomicField();
   virtual void write(ostream &out, int indent_level = 0) const;
   virtual void write(ostream &out, int indent_level = 0) const;
+  virtual void generate_hash(HashGenerator &hash) const;
 
 
 public:
 public:
   // These members define the primary interface to the atomic field
   // These members define the primary interface to the atomic field

+ 30 - 6
direct/src/dcparser/dcClass.cxx

@@ -4,6 +4,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "dcClass.h"
 #include "dcClass.h"
+#include "hashGenerator.h"
 #include "dcindent.h"
 #include "dcindent.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -162,9 +163,9 @@ DCClass() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DCClass::
 DCClass::
 ~DCClass() {
 ~DCClass() {
-  Fields::iterator ai;
-  for (ai = _fields.begin(); ai != _fields.end(); ++ai) {
-    delete (*ai);
+  Fields::iterator fi;
+  for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
+    delete (*fi);
   }
   }
 }
 }
 
 
@@ -190,14 +191,37 @@ write(ostream &out, int indent_level) const {
   }
   }
   out << " {  // index " << _number << "\n";
   out << " {  // index " << _number << "\n";
 
 
-  Fields::const_iterator ai;
-  for (ai = _fields.begin(); ai != _fields.end(); ++ai) {
-    (*ai)->write(out, indent_level + 2);
+  Fields::const_iterator fi;
+  for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
+    (*fi)->write(out, indent_level + 2);
   }
   }
 
 
   indent(out, indent_level) << "};\n";
   indent(out, indent_level) << "};\n";
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCClass::generate_hash
+//       Access: Public, Virtual
+//  Description: Accumulates the properties of this class into the
+//               hash.
+////////////////////////////////////////////////////////////////////
+void DCClass::
+generate_hash(HashGenerator &hash) const {
+  hash.add_string(_name);
+
+  hash.add_int(_parents.size());
+  Parents::const_iterator pi;
+  for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
+    hash.add_int((*pi)->get_number());
+  }
+
+  hash.add_int(_fields.size());
+  Fields::const_iterator fi;
+  for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
+    (*fi)->generate_hash(hash);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCClass::add_field
 //     Function: DCClass::add_field
 //       Access: Public
 //       Access: Public

+ 4 - 0
direct/src/dcparser/dcClass.h

@@ -12,6 +12,8 @@
 #include <vector>
 #include <vector>
 #include <map>
 #include <map>
 
 
+class HashGenerator;
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : DCClass
 // 	 Class : DCClass
 // Description : Defines a particular DistributedClass as read from an
 // Description : Defines a particular DistributedClass as read from an
@@ -37,6 +39,8 @@ public:
   ~DCClass();
   ~DCClass();
 
 
   void write(ostream &out, int indent_level = 0) const;
   void write(ostream &out, int indent_level = 0) const;
+  void generate_hash(HashGenerator &hash) const;
+
   bool add_field(DCField *field);
   bool add_field(DCField *field);
 
 
 public:
 public:

+ 16 - 0
direct/src/dcparser/dcField.cxx

@@ -4,6 +4,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "dcField.h"
 #include "dcField.h"
+#include "hashGenerator.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCField::get_number
 //     Function: DCField::get_number
@@ -59,3 +60,18 @@ as_molecular_field() {
 DCField::
 DCField::
 ~DCField() {
 ~DCField() {
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::generate_hash
+//       Access: Public, Virtual
+//  Description: Accumulates the properties of this field into the
+//               hash.
+////////////////////////////////////////////////////////////////////
+void DCField::
+generate_hash(HashGenerator &hash) const {
+  // It shouldn't be necessary to explicitly add _number to the
+  // hash--this is computed based on the relative position of this
+  // field with the other fields, so adding it explicitly will be
+  // redundant.  However, the field name is significant.
+  hash.add_string(_name);
+}

+ 2 - 0
direct/src/dcparser/dcField.h

@@ -10,6 +10,7 @@
 
 
 class DCAtomicField;
 class DCAtomicField;
 class DCMolecularField;
 class DCMolecularField;
+class HashGenerator;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : DCField
 // 	 Class : DCField
@@ -27,6 +28,7 @@ PUBLISHED:
 public:
 public:
   virtual ~DCField();
   virtual ~DCField();
   virtual void write(ostream &out, int indent_level = 0) const=0;
   virtual void write(ostream &out, int indent_level = 0) const=0;
+  virtual void generate_hash(HashGenerator &hash) const;
 
 
 public:
 public:
   int _number;
   int _number;

+ 41 - 9
direct/src/dcparser/dcFile.cxx

@@ -6,6 +6,7 @@
 #include "dcFile.h"
 #include "dcFile.h"
 #include "dcParserDefs.h"
 #include "dcParserDefs.h"
 #include "dcLexerDefs.h"
 #include "dcLexerDefs.h"
+#include "hashGenerator.h"
 
 
 #ifdef WITHIN_PANDA
 #ifdef WITHIN_PANDA
 #include <filename.h>
 #include <filename.h>
@@ -14,7 +15,7 @@
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::Constructor
 //     Function: DCFile::Constructor
-//       Access: Public
+//       Access: Published
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DCFile::
 DCFile::
@@ -23,7 +24,7 @@ DCFile() {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::Destructor
 //     Function: DCFile::Destructor
-//       Access: Public
+//       Access: Published
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DCFile::
 DCFile::
@@ -36,7 +37,7 @@ DCFile::
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::read
 //     Function: DCFile::read
-//       Access: Public
+//       Access: Published
 //  Description: Opens and reads the indicated .dc file by name.  The
 //  Description: Opens and reads the indicated .dc file by name.  The
 //               distributed classes defined in the file will be
 //               distributed classes defined in the file will be
 //               appended to the set of distributed classes already
 //               appended to the set of distributed classes already
@@ -67,7 +68,7 @@ read(Filename filename) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::read
 //     Function: DCFile::read
-//       Access: Public
+//       Access: Published
 //  Description: Parses the already-opened input stream for
 //  Description: Parses the already-opened input stream for
 //               distributed class descriptions.  The filename
 //               distributed class descriptions.  The filename
 //               parameter is optional and is only used when reporting
 //               parameter is optional and is only used when reporting
@@ -92,7 +93,7 @@ read(istream &in, const string &filename) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::write
 //     Function: DCFile::write
-//       Access: Public
+//       Access: Published
 //  Description: Opens the indicated filename for output and writes a
 //  Description: Opens the indicated filename for output and writes a
 //               parseable description of all the known distributed
 //               parseable description of all the known distributed
 //               classes to the file.
 //               classes to the file.
@@ -120,7 +121,7 @@ write(Filename filename) const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::write
 //     Function: DCFile::write
-//       Access: Public
+//       Access: Published
 //  Description: Writes a parseable description of all the known
 //  Description: Writes a parseable description of all the known
 //               distributed classes to the file.  The filename
 //               distributed classes to the file.  The filename
 //               parameter is optional and is only used when reporting
 //               parameter is optional and is only used when reporting
@@ -147,7 +148,7 @@ write(ostream &out, const string &filename) const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::get_num_classes
 //     Function: DCFile::get_num_classes
-//       Access: Public
+//       Access: Published
 //  Description: Returns the number of classes read from the .dc
 //  Description: Returns the number of classes read from the .dc
 //               file(s).
 //               file(s).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -158,7 +159,7 @@ get_num_classes() {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::get_class
 //     Function: DCFile::get_class
-//       Access: Public
+//       Access: Published
 //  Description: Returns the nth class read from the .dc file(s).
 //  Description: Returns the nth class read from the .dc file(s).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DCClass *DCFile::
 DCClass *DCFile::
@@ -169,7 +170,7 @@ get_class(int n) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::get_class_by_name
 //     Function: DCFile::get_class_by_name
-//       Access: Public
+//       Access: Published
 //  Description: Returns the class that has the indicated name, or
 //  Description: Returns the class that has the indicated name, or
 //               NULL if there is no such class.
 //               NULL if there is no such class.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -184,6 +185,37 @@ get_class_by_name(const string &name) {
   return (DCClass *)NULL;
   return (DCClass *)NULL;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCFile::get_hash
+//       Access: Published
+//  Description: Returns a 32-bit hash index associated with this
+//               file.  This number is guaranteed to be consistent if
+//               the contents of the file have not changed, and it is
+//               very likely to be different if the contents of the
+//               file do change.
+////////////////////////////////////////////////////////////////////
+long DCFile::
+get_hash() const {
+  HashGenerator hash;
+  generate_hash(hash);
+  return hash.get_hash();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCFile::generate_hash
+//       Access: Public, Virtual
+//  Description: Accumulates the properties of this file into the
+//               hash.
+////////////////////////////////////////////////////////////////////
+void DCFile::
+generate_hash(HashGenerator &hash) const {
+  hash.add_int(_classes.size());
+  Classes::const_iterator ci;
+  for (ci = _classes.begin(); ci != _classes.end(); ++ci) {
+    (*ci)->generate_hash(hash);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::add_class
 //     Function: DCFile::add_class
 //       Access: Public
 //       Access: Public

+ 5 - 0
direct/src/dcparser/dcFile.h

@@ -12,6 +12,8 @@
 #include <vector>
 #include <vector>
 #include <map>
 #include <map>
 
 
+class HashGenerator;
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : DCFile
 // 	 Class : DCFile
 // Description : Represents the complete list of Distributed Class
 // Description : Represents the complete list of Distributed Class
@@ -33,7 +35,10 @@ PUBLISHED:
 
 
   DCClass *get_class_by_name(const string &name);
   DCClass *get_class_by_name(const string &name);
 
 
+  long get_hash() const;
+
 public:
 public:
+  void generate_hash(HashGenerator &hash) const;
   bool add_class(DCClass *dclass);
   bool add_class(DCClass *dclass);
 
 
 public:
 public:

+ 18 - 0
direct/src/dcparser/dcMolecularField.cxx

@@ -5,6 +5,7 @@
 
 
 #include "dcMolecularField.h"
 #include "dcMolecularField.h"
 #include "dcAtomicField.h"
 #include "dcAtomicField.h"
+#include "hashGenerator.h"
 #include "dcindent.h"
 #include "dcindent.h"
 
 
 
 
@@ -79,3 +80,20 @@ write(ostream &out, int indent_level) const {
   out << ";  // field " << _number << "\n";
   out << ";  // field " << _number << "\n";
 }
 }
 
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCMolecularField::generate_hash
+//       Access: Public, Virtual
+//  Description: Accumulates the properties of this field into the
+//               hash.
+////////////////////////////////////////////////////////////////////
+void DCMolecularField::
+generate_hash(HashGenerator &hash) const {
+  DCField::generate_hash(hash);
+
+  hash.add_int(_fields.size());
+  Fields::const_iterator fi;
+  for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
+    (*fi)->generate_hash(hash);
+  }
+}

+ 1 - 0
direct/src/dcparser/dcMolecularField.h

@@ -30,6 +30,7 @@ PUBLISHED:
 public:
 public:
   DCMolecularField();
   DCMolecularField();
   virtual void write(ostream &out, int indent_level = 0) const;
   virtual void write(ostream &out, int indent_level = 0) const;
+  virtual void generate_hash(HashGenerator &hash) const;
 
 
 public:
 public:
   // These members define the primary interface to the molecular field
   // These members define the primary interface to the molecular field

+ 69 - 0
direct/src/dcparser/hashGenerator.cxx

@@ -0,0 +1,69 @@
+// Filename: hashGenerator.cxx
+// Created by:  drose (22Mar01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "hashGenerator.h"
+#include "primeNumberGenerator.h"
+
+// We multiply each consecutive integer by the next prime number and
+// add it to the total, so in theory we will truly generate a unique
+// hash number for each unique sequence of ints, as long as the number
+// of ints does not exceed the number of prime numbers we have, and we
+// do not overflow the limits of a 32-bit integer.
+
+// We do recycle the prime number table at some point, just to keep it
+// from growing insanely large, however, and we also truncate
+// everything to the low-order 32 bits, so we introduce ambiguity in
+// this way.
+
+static const int max_prime_numbers = 10000;
+static PrimeNumberGenerator primes;
+
+////////////////////////////////////////////////////////////////////
+//     Function: HashGenerator::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+HashGenerator::
+HashGenerator() {
+  _hash = 0;
+  _index = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: HashGenerator::add_int
+//       Access: Public
+//  Description: Adds another integer to the hash so far.
+////////////////////////////////////////////////////////////////////
+void HashGenerator::
+add_int(int num) {
+  nassertv(_index >= 0 && _index < max_prime_numbers);
+  _hash += (int)primes[_index] * num;
+  _index = (_index + 1) % max_prime_numbers;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: HashGenerator::add_string
+//       Access: Public
+//  Description: Adds a string to the hash, by breaking it down into a
+//               sequence of integers.
+////////////////////////////////////////////////////////////////////
+void HashGenerator::
+add_string(const string &str) {
+  add_int(str.length());
+  string::const_iterator si;
+  for (si = str.begin(); si != str.end(); ++si) {
+    add_int(*si);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: HashGenerator::get_hash
+//       Access: Public
+//  Description: Returns the hash number generated.
+////////////////////////////////////////////////////////////////////
+long HashGenerator::
+get_hash() const {
+  return _hash & 0xffffffff;
+}

+ 30 - 0
direct/src/dcparser/hashGenerator.h

@@ -0,0 +1,30 @@
+// Filename: hashGenerator.h
+// Created by:  drose (22Mar01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef DCHASHGENERATOR_H
+#define DCHASHGENERATOR_H
+
+#include "dcbase.h"
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : HashGenerator
+// Description : This class generates an arbitrary hash number from a
+//               sequence of ints.
+////////////////////////////////////////////////////////////////////
+class HashGenerator {
+public:
+  HashGenerator();
+
+  void add_int(int num);
+  void add_string(const string &str);
+
+  long get_hash() const;
+
+private:
+  long _hash;
+  int _index;
+};
+
+#endif

+ 55 - 0
direct/src/dcparser/primeNumberGenerator.cxx

@@ -0,0 +1,55 @@
+// Filename: primeNumberGenerator.cxx
+// Created by:  drose (22Mar01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "primeNumberGenerator.h"
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PrimeNumberGenerator::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+PrimeNumberGenerator::
+PrimeNumberGenerator() {
+  _primes.push_back(2);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PrimeNumberGenerator::Indexing operator
+//       Access: Public
+//  Description: Returns the nth prime number.  this[0] returns 2,
+//               this[1] returns 3; successively larger values of n
+//               return larger prime numbers, up to the largest prime
+//               number that can be represented in an int.
+////////////////////////////////////////////////////////////////////
+int PrimeNumberGenerator::
+operator [] (int n) {
+  nassertr(n >= 0, 0);
+
+  // Compute the prime numbers between the last-computed prime number
+  // and n.
+  int candidate = _primes.back() + 1;
+  while ((int)_primes.size() <= n) {
+    // Is candidate prime?  It is not if any one of the already-found
+    // prime numbers (up to its square root) divides it evenly.
+    bool maybe_prime = true;
+    int j = 0;
+    while (maybe_prime && _primes[j] * _primes[j] <= candidate) {
+      if ((_primes[j] * (candidate / _primes[j])) == candidate) {
+	// This one is not prime.
+	maybe_prime = false;
+      }
+      j++;
+      nassertr(j < (int)_primes.size(), 0)
+    }
+    if (maybe_prime) {
+      // Hey, we found a prime!
+      _primes.push_back(candidate);
+    }
+    candidate++;
+  }
+
+  return _primes[n];
+}

+ 30 - 0
direct/src/dcparser/primeNumberGenerator.h

@@ -0,0 +1,30 @@
+// Filename: primeNumberGenerator.h
+// Created by:  drose (22Mar01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef PRIMENUMBERGENERATOR_H
+#define PRIMENUMBERGENERATOR_H
+
+#include "dcbase.h"
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : PrimeNumberGenerator
+// Description : This class generates a table of prime numbers, up to
+//               the limit of an int.  For a given integer n, it will
+//               return the nth prime number.  This will involve a
+//               recompute step only if n is greater than any previous
+//               n.
+////////////////////////////////////////////////////////////////////
+class PrimeNumberGenerator {
+public:
+  PrimeNumberGenerator();
+  
+  int operator [] (int n);
+
+private:
+  typedef vector<int> Primes;
+  Primes _primes;
+};
+
+#endif