Browse Source

slightly better unpack exception generating

David Rose 17 years ago
parent
commit
f28396fead

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

@@ -494,8 +494,9 @@ receive_update(PyObject *distobj, DatagramIterator &di) const {
   PStatTimer timer(((DCClass *)this)->_class_update_pcollector);
 #endif
     DCPacker packer;
-    packer.set_unpack_data(di.get_remaining_bytes());
-
+    const char *data = (const char *)di.get_datagram().get_data();
+    packer.set_unpack_data(data + di.get_current_index(),
+                           di.get_remaining_size(), false);
 
     int field_id = packer.raw_unpack_uint16();
     DCField *field = get_field_by_index(field_id);
@@ -532,7 +533,9 @@ receive_update_broadcast_required(PyObject *distobj, DatagramIterator &di) const
   PStatTimer timer(((DCClass *)this)->_class_update_pcollector);
 #endif
   DCPacker packer;
-  packer.set_unpack_data(di.get_remaining_bytes());
+  const char *data = (const char *)di.get_datagram().get_data();
+  packer.set_unpack_data(data + di.get_current_index(),
+                         di.get_remaining_size(), false);
 
   int num_fields = get_num_inherited_fields();
   for (int i = 0; i < num_fields && !PyErr_Occurred(); ++i) {
@@ -568,7 +571,9 @@ receive_update_broadcast_required_owner(PyObject *distobj,
   PStatTimer timer(((DCClass *)this)->_class_update_pcollector);
 #endif
   DCPacker packer;
-  packer.set_unpack_data(di.get_remaining_bytes());
+  const char *data = (const char *)di.get_datagram().get_data();
+  packer.set_unpack_data(data + di.get_current_index(),
+                         di.get_remaining_size(), false);
 
   int num_fields = get_num_inherited_fields();
   for (int i = 0; i < num_fields && !PyErr_Occurred(); ++i) {
@@ -608,7 +613,9 @@ receive_update_all_required(PyObject *distobj, DatagramIterator &di) const {
   PStatTimer timer(((DCClass *)this)->_class_update_pcollector);
 #endif
   DCPacker packer;
-  packer.set_unpack_data(di.get_remaining_bytes());
+  const char *data = (const char *)di.get_datagram().get_data();
+  packer.set_unpack_data(data + di.get_current_index(),
+                         di.get_remaining_size(), false);
 
   int num_fields = get_num_inherited_fields();
   for (int i = 0; i < num_fields && !PyErr_Occurred(); ++i) {

+ 28 - 15
direct/src/dcparser/dcField.cxx

@@ -344,6 +344,7 @@ unpack_args(DCPacker &packer) const {
   nassertr(!packer.had_error(), NULL);
   nassertr(packer.get_current_field() == this, NULL);
 
+  size_t start_byte = packer.get_num_unpacked_bytes();
   PyObject *object = packer.unpack_object();
 
   if (!packer.had_error()) {
@@ -356,23 +357,35 @@ unpack_args(DCPacker &packer) const {
 
     return object;
   }
-  
-  ostringstream strm;
-  if (packer.had_pack_error()) {
-    strm << "Error unpacking to field " << get_name();
-  } else {
-    PyObject *str = PyObject_Str(object);
-    strm << "Found value outside specified range when unpacking field " 
-         << get_name() << ": " << PyString_AsString(str);
-    Py_DECREF(str);
-  }
 
-  /*
-  Datagram dg(data.data(), packer.get_num_unpacked_bytes());
-  dg.dump_hex(cerr);
-  */
+  if (!Notify::ptr()->has_assert_failed()) {
+    ostringstream strm;
+    PyObject *exc_type = PyExc_StandardError;
+
+    if (packer.had_pack_error()) {
+      strm << "Data error unpacking field ";
+      output(strm, true);
+      size_t length = packer.get_unpack_length() - start_byte;
+      strm << "\nGot data (" << (int)length << " bytes):\n";
+      Datagram dg(packer.get_unpack_data() + start_byte, length);
+      dg.dump_hex(strm);
+      size_t error_byte = packer.get_num_unpacked_bytes() - start_byte;
+      strm << "Error detected on byte " << error_byte
+           << " (" << hex << error_byte << dec << " hex)";
+
+      exc_type = PyExc_RuntimeError;
+    } else {
+      PyObject *str = PyObject_Str(object);
+      strm << "Value outside specified range when unpacking field " 
+           << get_name() << ": " << PyString_AsString(str);
+      Py_DECREF(str);
+      exc_type = PyExc_ValueError;
+    }
     
-  nassert_raise(strm.str());
+    string message = strm.str();
+    PyErr_SetString(exc_type, message.c_str());
+  }
+
   Py_XDECREF(object);
   return NULL;
 }

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

@@ -664,6 +664,33 @@ get_string() const {
   return _pack_data.get_string();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::get_unpack_length
+//       Access: Published
+//  Description: Returns the total number of bytes in the unpack data
+//               buffer.  This is the buffer used when unpacking; it
+//               is separate from the pack data returned by
+//               get_length(), which is filled during packing.
+////////////////////////////////////////////////////////////////////
+INLINE size_t DCPacker::
+get_unpack_length() const {
+  return _unpack_length;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::get_unpack_string
+//       Access: Published
+//  Description: Returns the unpack data buffer, as a string.
+//               This is the buffer used when unpacking; it is
+//               separate from the pack data returned by get_string(),
+//               which is filled during packing.  Also see
+//               get_unpack_data().
+////////////////////////////////////////////////////////////////////
+INLINE string DCPacker::
+get_unpack_string() const {
+  return string(_unpack_data, _unpack_length);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPacker::get_string
 //       Access: Published
@@ -736,6 +763,19 @@ get_write_pointer(size_t size) {
   return _pack_data.get_write_pointer(size);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::get_unpack_data
+//       Access: Public
+//  Description: Returns a read pointer to the unpack data buffer.
+//               This is the buffer used when unpacking; it is
+//               separate from the pack data returned by get_data(),
+//               which is filled during packing.
+////////////////////////////////////////////////////////////////////
+INLINE const char *DCPacker::
+get_unpack_data() const {
+  return _unpack_data;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPacker::StackElement::get_num_stack_elements_ever_allocated
 //       Access: Published, Static

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

@@ -123,6 +123,8 @@ PUBLISHED:
 
   INLINE size_t get_length() const;
   INLINE string get_string() const;
+  INLINE size_t get_unpack_length() const;
+  INLINE string get_unpack_string() const;
 public:
   INLINE void get_string(string &data) const;
   INLINE const char *get_data() const;
@@ -131,6 +133,8 @@ public:
   INLINE void append_data(const char *buffer, size_t size);
   INLINE char *get_write_pointer(size_t size);
 
+  INLINE const char *get_unpack_data() const;
+
 PUBLISHED:
   INLINE static int get_num_stack_elements_ever_allocated();