Browse Source

various refinements

David Rose 21 years ago
parent
commit
836cc8224d

+ 20 - 5
direct/src/dcparser/dcClass.cxx

@@ -482,6 +482,14 @@ pack_required_field(DCPacker &packer, PyObject *distobj,
     string field_name = field->get_name();
 
     if (!PyObject_HasAttrString(distobj, (char *)field_name.c_str())) {
+      // If the attribute is not defined, but the field has a default
+      // value specified, quietly pack the default value.
+      if (field->has_default_value()) {
+        packer.pack_default_value();
+        return true;
+      }
+
+      // If there is no default value specified, it's an error.
       ostringstream strm;
       strm << "Data element " << field_name
            << ", required by dc file for dclass " << get_name()
@@ -503,7 +511,7 @@ pack_required_field(DCPacker &packer, PyObject *distobj,
   const DCAtomicField *atom = field->as_atomic_field();
   if (atom == (DCAtomicField *)NULL) {
     ostringstream strm;
-    strm << "Cannot pack non-atomic field " << field->get_name()
+    strm << "Cannot pack molecular field " << field->get_name()
          << " for generate";
     nassert_raise(strm.str());
     return false;
@@ -547,6 +555,14 @@ pack_required_field(DCPacker &packer, PyObject *distobj,
   // Now we have to look up the getter on the distributed object
   // and call it.
   if (!PyObject_HasAttrString(distobj, (char *)getter_name.c_str())) {
+    // As above, if there's no getter but the field has a default
+    // value specified, quietly pack the default value.
+    if (field->has_default_value()) {
+      packer.pack_default_value();
+      return true;
+    }
+
+    // Otherwise, with no default value it's an error.
     ostringstream strm;
     strm << "Distributed class " << get_name()
          << " doesn't have getter named " << getter_name
@@ -671,10 +687,9 @@ ai_format_generate(PyObject *distobj, int do_id,
   int num_fields = get_num_inherited_fields();
   for (int i = 0; i < num_fields; i++) {
     DCField *field = get_inherited_field(i);
-    DCAtomicField *atom = field->as_atomic_field();
-    if (atom != (DCAtomicField *)NULL && atom->is_required()) {
-      packer.begin_pack(atom);
-      if (!pack_required_field(packer, distobj, atom)) {
+    if (field->is_required() && field->as_molecular_field() == NULL) {
+      packer.begin_pack(field);
+      if (!pack_required_field(packer, distobj, field)) {
         return Datagram();
       }
       packer.end_pack();

+ 49 - 8
direct/src/dcparser/dcPacker.cxx

@@ -464,7 +464,6 @@ push() {
             length = DCPackerInterface::do_unpack_uint32
               (_unpack_data + _unpack_p);
             _unpack_p += 4;
-            _pop_marker = _unpack_p + length;
           } else {
             length = DCPackerInterface::do_unpack_uint16
               (_unpack_data + _unpack_p);
@@ -1122,17 +1121,12 @@ clear() {
 void DCPacker::
 pack_class_object(const DCClass *dclass, PyObject *object) {
   PyObject *str = PyObject_Str(object);
-  cerr << "pack_class_object(" << dclass->get_name() << ", " 
-       << PyString_AsString(str) << ")\n";
   Py_DECREF(str);
   push();
-  while (more_nested_fields()) {
+  while (more_nested_fields() && !_pack_error) {
     const DCField *field = get_current_field()->as_field();
     nassertv(field != (DCField *)NULL);
-
-    if (!dclass->pack_required_field(*this, object, field)) {
-      break;
-    }
+    get_class_element(dclass, object, field);
   }
   pop();
 }
@@ -1257,3 +1251,50 @@ set_class_element(PyObject *class_def, PyObject *&object,
   }
 }
 #endif  // HAVE_PYTHON
+
+
+#ifdef HAVE_PYTHON
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::get_class_element
+//       Access: Private
+//  Description: Gets the current element from the Python object and
+//               packs it.
+////////////////////////////////////////////////////////////////////
+void DCPacker::
+get_class_element(const DCClass *dclass, PyObject *object, 
+                  const DCField *field) {
+  string field_name = field->get_name();
+  DCPackType pack_type = get_pack_type();
+
+  if (field_name.empty()) {
+    switch (pack_type) {
+    case PT_class:
+    case PT_switch:
+      // If the field has no name, but it is one of these container
+      // objects, we want to get its nested objects directly from
+      // the class.
+      push();
+      while (more_nested_fields() && !_pack_error) {
+        const DCField *field = get_current_field()->as_field();
+        nassertv(field != (DCField *)NULL);
+        get_class_element(dclass, object, field);
+      }
+      pop();
+      break;
+
+    default:
+      // Otherwise, we just pack the default value.
+      pack_default_value();
+    }
+
+  } else {
+    // If the field does have a name, we will want to get it from the
+    // class and pack it.  It just so happens that there's already a
+    // method that does this on DCClass.
+
+    if (!dclass->pack_required_field(*this, object, field)) {
+      _pack_error = true;
+    }
+  }
+}
+#endif  // HAVE_PYTHON

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

@@ -183,6 +183,8 @@ private:
   PyObject *unpack_class_object(const DCClass *dclass);
   void set_class_element(PyObject *class_def, PyObject *&object, 
                          const DCField *field);
+  void get_class_element(const DCClass *dclass, PyObject *object, 
+                         const DCField *field);
 #endif
 
 private:

+ 7 - 1
direct/src/dcparser/dcPackerCatalog.cxx

@@ -328,7 +328,13 @@ update_switch_fields(const DCSwitchParameter *switch_parameter,
   // because we must have come across the DCSwitch when building the
   // catalog the first time.
   SwitchPrefixes::const_iterator pi = _switch_prefixes.find(switch_parameter);
-  nassertr(pi != _switch_prefixes.end(), NULL);
+  if (pi == _switch_prefixes.end()) {
+    // If it's not stored in the record, the switch must be hidden
+    // within some non-seekable object, like an array; in this case,
+    // never mind.
+    return this;
+  }
+
   string name_prefix = (*pi).second;
 
   // Start by creating a new DCPackerCatalog object that contains all

+ 24 - 0
direct/src/dcparser/dcPackerInterface.cxx

@@ -350,12 +350,36 @@ bool DCPackerInterface::
 unpack_skip(const char *data, size_t length, size_t &p,
             bool &pack_error) const {
   if (_has_fixed_byte_size) {
+    // If this field has a fixed byte size, it's easy to skip.
     p += _fixed_byte_size;
     if (p > length) {
       pack_error = true;
     }
     return true;
   }
+
+  if (_has_nested_fields && _num_length_bytes != 0) {
+    // If we have a length prefix, use that for skipping.
+    if (p + _num_length_bytes > length) {
+      pack_error = true;
+      
+    } else {
+      if (_num_length_bytes == 4) {
+        size_t this_length = do_unpack_uint32(data + p);
+        p += this_length + 4;
+      } else {
+        size_t this_length = do_unpack_uint16(data + p);
+        p += this_length + 2;
+      }
+      if (p > length) {
+        pack_error = true;
+      }
+    }
+    return true;
+  }
+
+  // Otherwise, we don't know how to skip this field (presumably it
+  // can be skipped by skipping over its nested fields individually).
   return false;
 }
 

File diff suppressed because it is too large
+ 269 - 263
direct/src/dcparser/dcParser.cxx.prebuilt


+ 19 - 5
direct/src/dcparser/dcParser.yxx

@@ -116,6 +116,7 @@ dc_cleanup_parser() {
 
 %type <u.atomic> atomic_name
 %type <u.s_int> server_flags
+%type <u.s_int> no_server_flags
 %type <u.dclass> dclass_or_struct
 %type <u.dclass> dclass_name
 %type <u.dclass> dclass
@@ -303,6 +304,8 @@ dclass_fields:
 {
   if (!current_class->add_field($2)) {
     yyerror("Duplicate field name: " + $2->get_name());
+  } else if ($2->get_number() < 0) {
+    yyerror("A non-network field cannot be stored on a dclass");
   }
 }
         ;
@@ -313,9 +316,10 @@ dclass_field:
   $$ = $1;
   $$->set_flags($2);
 }
-	| molecular_field
+	| molecular_field no_server_flags
 	| unnamed_parameter_with_default server_flags ';'
 {
+  yyerror("Unnamed parameters are not allowed on a dclass");
   $$ = $1;
   $$->set_flags($2);
 }
@@ -388,13 +392,13 @@ struct_fields:
         ;
 
 struct_field:
-	atomic_field
-	| molecular_field
-	| unnamed_parameter_with_default ';'
+	atomic_field no_server_flags
+	| molecular_field no_server_flags
+	| unnamed_parameter_with_default no_server_flags ';'
 {
   $$ = $1;
 }
-	| named_parameter_with_default
+	| named_parameter_with_default no_server_flags
 {
   $$ = $1;
 }
@@ -987,6 +991,16 @@ server_flags:
 }
         ;
 
+no_server_flags:
+        server_flags
+{
+  if ($1 != 0) {
+    yyerror("Server flags are not allowed here.");
+  }
+  $$ = $1;
+}
+	;
+
 molecular_field:
         IDENTIFIER ':'
 {

Some files were not shown because too many files changed in this diff