Browse Source

regularize DCField::unpack_*

David Rose 21 years ago
parent
commit
6a406c9196

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

@@ -287,7 +287,9 @@ receive_update(PyObject *distobj, DatagramIterator &di) const {
   int field_id = packer.raw_unpack_uint16();
   DCField *field = get_inherited_field(field_id);
   nassertv_always(field != NULL);
+  packer.begin_unpack(field);
   field->receive_update(packer, distobj);
+  packer.end_unpack();
 
   di.skip_bytes(packer.get_num_unpacked_bytes());
 }
@@ -313,7 +315,11 @@ receive_update_broadcast_required(PyObject *distobj, DatagramIterator &di) const
     DCAtomicField *atom = field->as_atomic_field();
     if (atom != (DCAtomicField *)NULL &&
         atom->is_required() && atom->is_broadcast()) {
+      packer.begin_unpack(atom);
       atom->receive_update(packer, distobj);
+      if (!packer.end_unpack()) {
+        break;
+      }
     }
   }
 
@@ -340,7 +346,11 @@ receive_update_all_required(PyObject *distobj, DatagramIterator &di) const {
     DCField *field = get_inherited_field(i);
     DCAtomicField *atom = field->as_atomic_field();
     if (atom != (DCAtomicField *)NULL && atom->is_required()) {
+      packer.begin_unpack(atom);
       atom->receive_update(packer, distobj);
+      if (!packer.end_unpack()) {
+        break;
+      }
     }
   }
 
@@ -379,7 +389,9 @@ direct_update(PyObject *distobj, const string &field_name,
 
   DCPacker packer;
   packer.set_unpack_data(value_blob);
+  packer.begin_unpack(field);
   field->receive_update(packer, distobj);
+  packer.end_unpack();
 }
 #endif  // HAVE_PYTHON
 
@@ -504,9 +516,7 @@ client_format_update(const string &field_name, int do_id,
     return Datagram();
   }
 
-  DCPacker packer;
-  field->client_format_update(packer, do_id, args);
-  return Datagram(packer.get_data(), packer.get_length());
+  return field->client_format_update(do_id, args);
 }
 #endif  // HAVE_PYTHON
 
@@ -530,9 +540,7 @@ ai_format_update(const string &field_name, int do_id,
     return Datagram();
   }
 
-  DCPacker packer;
-  field->ai_format_update(packer, do_id, to_id, from_id, args);
-  return Datagram(packer.get_data(), packer.get_length());
+  return field->ai_format_update(do_id, to_id, from_id, args);
 }
 #endif  // HAVE_PYTHON
 
@@ -576,9 +584,11 @@ ai_format_generate(PyObject *distobj, int do_id,
     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)) {
         return Datagram();
       }
+      packer.end_pack();
     }
   }
 
@@ -601,9 +611,11 @@ ai_format_generate(PyObject *distobj, int do_id,
         return Datagram();
       }
 
+      packer.begin_pack(field);
       if (!pack_required_field(packer, distobj, field)) {
         return Datagram();
       }
+      packer.end_pack();
     }
   }
 

+ 50 - 21
direct/src/dcparser/dcField.cxx

@@ -186,13 +186,19 @@ validate_ranges(const string &packed_data) const {
 //  Description: Packs the Python arguments from the indicated tuple
 //               into the packer.  Returns true on success, false on
 //               failure.
+//
+//               It is assumed that the packer is currently positioned
+//               on this field.
 ////////////////////////////////////////////////////////////////////
 bool DCField::
 pack_args(DCPacker &packer, PyObject *sequence) const {
+  nassertr(!packer.had_error(), false);
+  nassertr(packer.get_current_field() == this, false);
+
   nassertr(PySequence_Check(sequence), false);
-  packer.begin_pack(this);
+
   packer.pack_object(sequence);
-  if (packer.end_pack()) {
+  if (!packer.had_error()) {
     /*
     PyObject *str = PyObject_Str(sequence);
     cerr << "pack " << get_name() << PyString_AsString(str) << "\n";
@@ -228,17 +234,19 @@ pack_args(DCPacker &packer, PyObject *sequence) const {
 //       Access: Published
 //  Description: Unpacks the values from the packer, beginning at
 //               the current point in the unpack_buffer, into a Python
-//               tuple and returns the tuple.  If there are remaining
-//               bytes in the unpack buffer, they are ignored (but the
-//               packer is left at the first unread byte).
+//               tuple and returns the tuple.
+//
+//               It is assumed that the packer is currently positioned
+//               on this field.
 ////////////////////////////////////////////////////////////////////
 PyObject *DCField::
 unpack_args(DCPacker &packer) const {
-  packer.begin_unpack(this);
+  nassertr(!packer.had_error(), NULL);
+  nassertr(packer.get_current_field() == this, NULL);
 
   PyObject *object = packer.unpack_object();
 
-  if (packer.end_unpack()) {
+  if (!packer.had_error()) {
     // Successfully unpacked.
     /*
     PyObject *str = PyObject_Str(object);
@@ -265,7 +273,8 @@ unpack_args(DCPacker &packer) const {
   */
     
   nassert_raise(strm.str());
-  return object;
+  Py_XDECREF(object);
+  return NULL;
 }
 #endif  // HAVE_PYTHON
 
@@ -281,16 +290,18 @@ void DCField::
 receive_update(DCPacker &packer, PyObject *distobj) const {
   PyObject *args = unpack_args(packer);
 
-  if (PyObject_HasAttrString(distobj, (char *)_name.c_str())) {
-    PyObject *func = PyObject_GetAttrString(distobj, (char *)_name.c_str());
-    nassertv(func != (PyObject *)NULL);
-
-    PyObject *result = PyObject_CallObject(func, args);
-    Py_XDECREF(result);
-    Py_DECREF(func);
+  if (args != (PyObject *)NULL) {
+    if (PyObject_HasAttrString(distobj, (char *)_name.c_str())) {
+      PyObject *func = PyObject_GetAttrString(distobj, (char *)_name.c_str());
+      nassertv(func != (PyObject *)NULL);
+      
+      PyObject *result = PyObject_CallObject(func, args);
+      Py_XDECREF(result);
+      Py_DECREF(func);
+    }
+    
+    Py_DECREF(args);
   }
-
-  Py_DECREF(args);
 }
 #endif  // HAVE_PYTHON
 
@@ -302,12 +313,21 @@ receive_update(DCPacker &packer, PyObject *distobj) const {
 //               to send an update for the indicated distributed
 //               object from the client.
 ////////////////////////////////////////////////////////////////////
-void DCField::
-client_format_update(DCPacker &packer, int do_id, PyObject *args) const {
+Datagram DCField::
+client_format_update(int do_id, PyObject *args) const {
+  DCPacker packer;
+
   packer.raw_pack_uint16(CLIENT_OBJECT_UPDATE_FIELD);
   packer.raw_pack_uint32(do_id);
   packer.raw_pack_uint16(_number);
+
+  packer.begin_pack(this);
   pack_args(packer, args);
+  if (!packer.end_pack()) {
+    return Datagram();
+  }
+
+  return Datagram(packer.get_data(), packer.get_length());
 }
 #endif  // HAVE_PYTHON
 
@@ -319,15 +339,24 @@ client_format_update(DCPacker &packer, int do_id, PyObject *args) const {
 //               to send an update for the indicated distributed
 //               object from the AI.
 ////////////////////////////////////////////////////////////////////
-void DCField::
-ai_format_update(DCPacker &packer, int do_id, int to_id, int from_id, PyObject *args) const {
+Datagram DCField::
+ai_format_update(int do_id, int to_id, int from_id, PyObject *args) const {
+  DCPacker packer;
+
   packer.raw_pack_uint32(to_id);
   packer.raw_pack_uint32(from_id);
   packer.raw_pack_uint8('A');
   packer.raw_pack_uint16(STATESERVER_OBJECT_UPDATE_FIELD);
   packer.raw_pack_uint32(do_id);
   packer.raw_pack_uint16(_number);
+
+  packer.begin_pack(this);
   pack_args(packer, args);
+  if (!packer.end_pack()) {
+    return Datagram();
+  }
+
+  return Datagram(packer.get_data(), packer.get_length());
 }
 #endif  // HAVE_PYTHON
 

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

@@ -60,8 +60,9 @@ PUBLISHED:
 
   void receive_update(DCPacker &packer, PyObject *distobj) const;
 
-  void client_format_update(DCPacker &packer, int do_id, PyObject *args) const;
-  void ai_format_update(DCPacker &packer, int do_id, int to_id, int from_id, PyObject *args) const;
+  Datagram client_format_update(int do_id, PyObject *args) const;
+  Datagram ai_format_update(int do_id, int to_id, int from_id,
+                            PyObject *args) const;
 #endif 
 
 public:

+ 14 - 0
direct/src/dcparser/dcPacker.I

@@ -588,6 +588,20 @@ had_range_error() const {
   return _range_error;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::had_error
+//       Access: Published
+//  Description: Returns true if there has been any error (either a
+//               pack error or a range error) since the most recent
+//               call to begin().  If this returns true, then the
+//               matching call to end() will indicate an error
+//               (false).
+////////////////////////////////////////////////////////////////////
+INLINE bool DCPacker::
+had_error() const {
+  return _range_error || _pack_error;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPacker::get_num_unpacked_bytes
 //       Access: Published

+ 3 - 3
direct/src/dcparser/dcPacker.cxx

@@ -104,7 +104,7 @@ end_pack() {
 
   clear();
 
-  return !_pack_error && !_range_error;
+  return !had_error();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -205,7 +205,7 @@ end_unpack() {
 
   clear();
 
-  return !_pack_error && !_range_error;
+  return !had_error();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -273,7 +273,7 @@ end_repack() {
   _mode = M_idle;
   clear();
 
-  return !_pack_error && !_range_error;
+  return !had_error();
 }
 
 ////////////////////////////////////////////////////////////////////

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

@@ -118,6 +118,7 @@ PUBLISHED:
 
   INLINE bool had_pack_error() const;
   INLINE bool had_range_error() const;
+  INLINE bool had_error() const;
   INLINE size_t get_num_unpacked_bytes() const;
 
   INLINE string get_string() const;