Browse Source

dcparser: use vector_uchar for blobs, step towards Python 3 compat

Closes #298
rdb 7 years ago
parent
commit
e4f493b872

+ 72 - 0
direct/src/dcparser/dcArrayParameter.cxx

@@ -262,6 +262,38 @@ pack_string(DCPackData &pack_data, const string &value,
   }
 }
 
+/**
+ * Packs the indicated numeric or string value into the stream.
+ */
+void DCArrayParameter::
+pack_blob(DCPackData &pack_data, const vector_uchar &value,
+          bool &pack_error, bool &range_error) const {
+  // We can only pack a string if the array element type is char or int8.
+  DCSimpleParameter *simple_type = _element_type->as_simple_parameter();
+  if (simple_type == nullptr) {
+    pack_error = true;
+    return;
+  }
+
+  size_t blob_size = value.size();
+
+  switch (simple_type->get_type()) {
+  case ST_char:
+  case ST_uint8:
+  case ST_int8:
+    _array_size_range.validate(blob_size, range_error);
+    if (_num_length_bytes != 0) {
+      nassertv(_num_length_bytes == 2);
+      do_pack_uint16(pack_data.get_write_pointer(2), blob_size);
+    }
+    pack_data.append_data((const char *)value.data(), blob_size);
+    break;
+
+  default:
+    pack_error = true;
+  }
+}
+
 /**
  * Packs the arrayParameter's specified default value (or a sensible default
  * if no value is specified) into the stream.  Returns true if the default
@@ -339,6 +371,46 @@ unpack_string(const char *data, size_t length, size_t &p, string &value,
   }
 }
 
+/**
+ * Unpacks the current numeric or string value from the stream.
+ */
+void DCArrayParameter::
+unpack_blob(const char *data, size_t length, size_t &p, vector_uchar &value,
+            bool &pack_error, bool &range_error) const {
+  // We can only unpack a string if the array element type is char or int8.
+  DCSimpleParameter *simple_type = _element_type->as_simple_parameter();
+  if (simple_type == nullptr) {
+    pack_error = true;
+    return;
+  }
+
+  size_t blob_size;
+
+  switch (simple_type->get_type()) {
+  case ST_char:
+  case ST_uint8:
+  case ST_int8:
+    if (_num_length_bytes != 0) {
+      blob_size = do_unpack_uint16(data + p);
+      p += 2;
+    } else {
+      nassertv(_array_size >= 0);
+      blob_size = _array_size;
+    }
+    if (p + blob_size > length) {
+      pack_error = true;
+      return;
+    }
+    value = vector_uchar((const unsigned char *)data + p,
+                         (const unsigned char *)data + p + blob_size);
+    p += blob_size;
+    break;
+
+  default:
+    pack_error = true;
+  }
+}
+
 /**
  * Returns true if the other interface is bitwise the same as this one--that
  * is, a uint32 only matches a uint32, etc.  Names of components, and range

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

@@ -51,9 +51,13 @@ public:
   virtual void generate_hash(HashGenerator &hashgen) const;
   virtual void pack_string(DCPackData &pack_data, const std::string &value,
                            bool &pack_error, bool &range_error) const;
+  virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value,
+                         bool &pack_error, bool &range_error) const;
   virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
   virtual void unpack_string(const char *data, size_t length, size_t &p,
                              std::string &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_blob(const char *data, size_t length, size_t &p,
+                           vector_uchar &value, bool &pack_error, bool &range_error) const;
 
 protected:
   virtual bool do_check_match(const DCPackerInterface *other) const;

+ 5 - 5
direct/src/dcparser/dcAtomicField.cxx

@@ -88,11 +88,11 @@ get_element(int n) const {
  * If the element is an array-type element, the returned value will include
  * the two-byte length preceding the array data.
  *
- * This is deprecated; use get_element() instead.
+ * @deprecated use get_element() instead.
  */
-string DCAtomicField::
+vector_uchar DCAtomicField::
 get_element_default(int n) const {
-  nassertr(n >= 0 && n < (int)_elements.size(), string());
+  nassertr(n >= 0 && n < (int)_elements.size(), vector_uchar());
   return _elements[n]->get_default_value();
 }
 
@@ -100,7 +100,7 @@ get_element_default(int n) const {
  * Returns true if the nth element of the field has a default value specified,
  * false otherwise.
  *
- * This is deprecated; use get_element() instead.
+ * @deprecated use get_element() instead.
  */
 bool DCAtomicField::
 has_element_default(int n) const {
@@ -113,7 +113,7 @@ has_element_default(int n) const {
  * for documentary purposes; it does not generally affect operation.  If a
  * name is not specified, this will be the empty string.
  *
- * This method is deprecated; use get_element()->get_name() instead.
+ * @deprecated use get_element()->get_name() instead.
  */
 string DCAtomicField::
 get_element_name(int n) const {

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

@@ -40,7 +40,7 @@ PUBLISHED:
   DCParameter *get_element(int n) const;
 
   // These five methods are deprecated and will be removed soon.
-  std::string get_element_default(int n) const;
+  vector_uchar get_element_default(int n) const;
   bool has_element_default(int n) const;
   std::string get_element_name(int n) const;
   DCSubatomicType get_element_type(int n) const;

+ 9 - 2
direct/src/dcparser/dcClass.cxx

@@ -587,7 +587,7 @@ receive_update_other(PyObject *distobj, DatagramIterator &di) const {
  */
 void DCClass::
 direct_update(PyObject *distobj, const string &field_name,
-              const string &value_blob) {
+              const vector_uchar &value_blob) {
   DCField *field = get_field_by_name(field_name);
   nassertv_always(field != nullptr);
 
@@ -606,7 +606,14 @@ direct_update(PyObject *distobj, const string &field_name,
 void DCClass::
 direct_update(PyObject *distobj, const string &field_name,
               const Datagram &datagram) {
-  direct_update(distobj, field_name, datagram.get_message());
+  DCField *field = get_field_by_name(field_name);
+  nassertv_always(field != nullptr);
+
+  DCPacker packer;
+  packer.set_unpack_data((const char *)datagram.get_data(), datagram.get_length(), false);
+  packer.begin_unpack(field);
+  field->receive_update(packer, distobj);
+  packer.end_unpack();
 }
 #endif  // HAVE_PYTHON
 

+ 1 - 1
direct/src/dcparser/dcClass.h

@@ -95,7 +95,7 @@ PUBLISHED:
   void receive_update_other(PyObject *distobj, DatagramIterator &di) const;
 
   void direct_update(PyObject *distobj, const std::string &field_name,
-                     const std::string &value_blob);
+                     const vector_uchar &value_blob);
   void direct_update(PyObject *distobj, const std::string &field_name,
                      const Datagram &datagram);
   bool pack_required_field(Datagram &datagram, PyObject *distobj,

+ 3 - 3
direct/src/dcparser/dcField.I

@@ -42,7 +42,7 @@ has_default_value() const {
  * explicitly set (e.g.  has_default_value() returns true), returns that
  * value; otherwise, returns an implicit default for the field.
  */
-INLINE const std::string &DCField::
+INLINE const vector_uchar &DCField::
 get_default_value() const {
   if (_default_value_stale) {
     ((DCField *)this)->refresh_default_value();
@@ -172,8 +172,8 @@ set_class(DCClass *dclass) {
  * Establishes a default value for this field.
  */
 INLINE void DCField::
-set_default_value(const std::string &default_value) {
-  _default_value = default_value;
+set_default_value(vector_uchar default_value) {
+  _default_value = std::move(default_value);
   _has_default_value = true;
   _default_value_stale = false;
 }

+ 10 - 9
direct/src/dcparser/dcField.cxx

@@ -162,7 +162,7 @@ as_parameter() const {
  * is an error.
  */
 string DCField::
-format_data(const string &packed_data, bool show_field_names) {
+format_data(const vector_uchar &packed_data, bool show_field_names) {
   DCPacker packer;
   packer.set_unpack_data(packed_data);
   packer.begin_unpack(this);
@@ -178,20 +178,20 @@ format_data(const string &packed_data, bool show_field_names) {
  * above) that represents the value of this field, parse the string and return
  * the corresponding packed data.  Returns empty string if there is an error.
  */
-string DCField::
+vector_uchar DCField::
 parse_string(const string &formatted_string) {
   DCPacker packer;
   packer.begin_pack(this);
   if (!packer.parse_and_pack(formatted_string)) {
     // Parse error.
-    return string();
+    return vector_uchar();
   }
   if (!packer.end_pack()) {
     // Data type mismatch.
-    return string();
+    return vector_uchar();
   }
 
-  return packer.get_string();
+  return packer.get_bytes();
 }
 
 /**
@@ -200,7 +200,7 @@ parse_string(const string &formatted_string) {
  * record.  Returns true if all fields are valid, false otherwise.
  */
 bool DCField::
-validate_ranges(const string &packed_data) const {
+validate_ranges(const vector_uchar &packed_data) const {
   DCPacker packer;
   packer.set_unpack_data(packed_data);
   packer.begin_unpack(this);
@@ -209,7 +209,7 @@ validate_ranges(const string &packed_data) const {
     return false;
   }
 
-  return (packer.get_num_unpacked_bytes() == packed_data.length());
+  return (packer.get_num_unpacked_bytes() == packed_data.size());
 }
 
 #ifdef HAVE_PYTHON
@@ -488,7 +488,7 @@ pack_default_value(DCPackData &pack_data, bool &) const {
   // The default behavior is to pack the default value if we got it;
   // otherwise, to return false and let the packer visit our nested elements.
   if (!_default_value_stale) {
-    pack_data.append_data(_default_value.data(), _default_value.length());
+    pack_data.append_data((const char *)_default_value.data(), _default_value.size());
     return true;
   }
 
@@ -566,7 +566,8 @@ refresh_default_value() {
   if (!packer.end_pack()) {
     std::cerr << "Error while packing default value for " << get_name() << "\n";
   } else {
-    _default_value.assign(packer.get_data(), packer.get_length());
+    const unsigned char *data = (const unsigned char *)packer.get_data();
+    _default_value = vector_uchar(data, data + packer.get_length());
   }
   _default_value_stale = false;
 }

+ 6 - 6
direct/src/dcparser/dcField.h

@@ -53,13 +53,13 @@ PUBLISHED:
   virtual DCParameter *as_parameter();
   virtual const DCParameter *as_parameter() const;
 
-  std::string format_data(const std::string &packed_data, bool show_field_names = true);
-  std::string parse_string(const std::string &formatted_string);
+  std::string format_data(const vector_uchar &packed_data, bool show_field_names = true);
+  vector_uchar parse_string(const std::string &formatted_string);
 
-  bool validate_ranges(const std::string &packed_data) const;
+  bool validate_ranges(const vector_uchar &packed_data) const;
 
   INLINE bool has_default_value() const;
-  INLINE const std::string &get_default_value() const;
+  INLINE const vector_uchar &get_default_value() const;
 
   INLINE bool is_bogus_field() const;
 
@@ -98,7 +98,7 @@ public:
 
   INLINE void set_number(int number);
   INLINE void set_class(DCClass *dclass);
-  INLINE void set_default_value(const std::string &default_value);
+  INLINE void set_default_value(vector_uchar default_value);
 
 #ifdef HAVE_PYTHON
   static std::string get_pystr(PyObject *value);
@@ -115,7 +115,7 @@ protected:
   bool _bogus_field;
 
 private:
-  std::string _default_value;
+  vector_uchar _default_value;
 
 #ifdef WITHIN_PANDA
   PStatCollector _field_update_pcollector;

File diff suppressed because it is too large
+ 160 - 142
direct/src/dcparser/dcLexer.cxx.prebuilt


+ 31 - 31
direct/src/dcparser/dcLexer.lxx

@@ -1,7 +1,7 @@
 /*
 // Filename: dcLexer.lxx
 // Created by:  drose (05Oct00)
-// 
+//
 ////////////////////////////////////////////////////////////////////
 */
 
@@ -103,12 +103,12 @@ dcyyerror(const std::string &msg) {
   if (!dc_filename.empty()) {
     cerr << " in " << dc_filename;
   }
-  cerr 
+  cerr
     << " at line " << line_number << ", column " << col_number << ":\n"
     << current_line << "\n";
-  indent(cerr, col_number-1) 
+  indent(cerr, col_number-1)
     << "^\n" << msg << "\n\n";
-  
+
   error_count++;
 }
 
@@ -120,10 +120,10 @@ dcyywarning(const std::string &msg) {
   if (!dc_filename.empty()) {
     cerr << " in " << dc_filename;
   }
-  cerr 
+  cerr
     << " at line " << line_number << ", column " << col_number << ":\n"
     << current_line << "\n";
-  indent(cerr, col_number-1) 
+  indent(cerr, col_number-1)
     << "^\n" << msg << "\n\n";
 
   warning_count++;
@@ -313,9 +313,9 @@ scan_quoted_string(char quote_mark) {
 
 // scan_hex_string reads a string of hexadecimal digits delimited by
 // angle brackets and returns the representative string.
-static std::string
+static vector_uchar
 scan_hex_string() {
-  std::string result;
+  vector_uchar result;
 
   // We don't touch the current line number and column number during
   // scanning, so that if we detect an error while scanning the string
@@ -345,24 +345,24 @@ scan_hex_string() {
       line_number = line;
       col_number = col;
       dcyyerror("Invalid hex digit.");
-      return std::string();
+      return vector_uchar();
     }
 
     odd = !odd;
     if (odd) {
       last = value;
     } else {
-      result += (char)((last << 4) | value);
+      result.push_back((unsigned char)((last << 4) | value));
     }
     c = read_char(line, col);
   }
 
   if (c == EOF) {
     dcyyerror("This hex string is unterminated.");
-    return std::string();
+    return vector_uchar();
   } else if (odd) {
     dcyyerror("Odd number of hex digits.");
-    return std::string();
+    return vector_uchar();
   }
 
   line_number = line;
@@ -382,7 +382,7 @@ eat_c_comment() {
   int col = col_number;
 
   int c, last_c;
-  
+
   last_c = '\0';
   c = read_char(line, col);
   while (c != EOF && !(last_c == '*' && c == '/')) {
@@ -440,12 +440,12 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
   yyless(1);
 }
 
-[ \t\r] { 
+[ \t\r] {
   // Eat whitespace.
   accept();
 }
 
-"//".* { 
+"//".* {
   // Eat C++-style comments.
   accept();
 }
@@ -453,7 +453,7 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
 "/*" {
   // Eat C-style comments.
   accept();
-  eat_c_comment(); 
+  eat_c_comment();
 }
 
 
@@ -607,7 +607,7 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
   return KW_CHAR;
 }
 
-{UNSIGNED_INTEGERNUM} { 
+{UNSIGNED_INTEGERNUM} {
   // An unsigned integer number.
   accept();
 
@@ -626,11 +626,11 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
     dcyylval.u.uint64 = next_value + (*p - '0');
     ++p;
   }
-  
+
   return UNSIGNED_INTEGER;
 }
 
-{SIGNED_INTEGERNUM} { 
+{SIGNED_INTEGERNUM} {
   // A signed integer number.
   accept();
 
@@ -671,14 +671,14 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
       dcyyerror("Number out of range.");
       dcyylval.u.int64 = 1;
     }
-  }    
-  
+  }
+
   return SIGNED_INTEGER;
 }
 
 {UNSIGNED_HEXNUM} {
   // A hexadecimal integer number.
-  accept(); 
+  accept();
 
   // As above, we'll decode the hex string by hand.
   dcyylval.str = dcyytext;
@@ -700,15 +700,15 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
     ++p;
   }
 
-  return UNSIGNED_INTEGER; 
+  return UNSIGNED_INTEGER;
 }
 
-{REALNUM} { 
+{REALNUM} {
   // A floating-point number.
-  accept(); 
-  dcyylval.u.real = patof(dcyytext); 
+  accept();
+  dcyylval.u.real = patof(dcyytext);
   dcyylval.str = dcyytext;
-  return REAL; 
+  return REAL;
 }
 
 ["] {
@@ -728,11 +728,11 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
 [<] {
   // Long hex string.
   accept();
-  dcyylval.str = scan_hex_string();
+  dcyylval.bytes = scan_hex_string();
   return HEX_STRING;
 }
 
-[A-Za-z_][A-Za-z_0-9]* { 
+[A-Za-z_][A-Za-z_0-9]* {
   // Identifier or keyword.
   accept();
   dcyylval.str = dcyytext;
@@ -750,7 +750,7 @@ REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
 
 . {
   // Send any other printable character as itself.
-  accept(); 
+  accept();
   return dcyytext[0];
 }
-  
+

+ 107 - 9
direct/src/dcparser/dcPacker.I

@@ -216,17 +216,31 @@ pack_string(const std::string &value) {
   }
 }
 
+/**
+ * Packs the indicated numeric or string value into the stream.
+ */
+INLINE void DCPacker::
+pack_blob(const vector_uchar &value) {
+  nassertv(_mode == M_pack || _mode == M_repack);
+  if (_current_field == nullptr) {
+    _pack_error = true;
+  } else {
+    _current_field->pack_blob(_pack_data, value, _pack_error, _range_error);
+    advance();
+  }
+}
+
 /**
  * Adds the indicated string value into the stream, representing a single pre-
  * packed field element, or a whole group of field elements at once.
  */
 INLINE void DCPacker::
-pack_literal_value(const std::string &value) {
+pack_literal_value(const vector_uchar &value) {
   nassertv(_mode == M_pack || _mode == M_repack);
   if (_current_field == nullptr) {
     _pack_error = true;
   } else {
-    _pack_data.append_data(value.data(), value.length());
+    _pack_data.append_data((const char *)value.data(), value.size());
     advance();
   }
 }
@@ -345,16 +359,36 @@ unpack_string() {
   return value;
 }
 
+/**
+ * Unpacks the current binary data value from the stream.
+ */
+INLINE vector_uchar DCPacker::
+unpack_blob() {
+  vector_uchar value;
+  nassertr(_mode == M_unpack, value);
+  if (_current_field == nullptr) {
+    _pack_error = true;
+
+  } else {
+    _current_field->unpack_blob(_unpack_data, _unpack_length, _unpack_p,
+                                 value, _pack_error, _range_error);
+    advance();
+  }
+
+  return value;
+}
+
 /**
  * Returns the literal string that represents the packed value of the current
  * field, and advances the field pointer.
  */
-INLINE std::string DCPacker::
+INLINE vector_uchar DCPacker::
 unpack_literal_value() {
   size_t start = _unpack_p;
   unpack_skip();
-  nassertr(_unpack_p >= start, std::string());
-  return std::string(_unpack_data + start, _unpack_p - start);
+  nassertr(_unpack_p >= start, vector_uchar());
+  return vector_uchar((const unsigned char *)_unpack_data + start,
+                      (const unsigned char *)_unpack_data + _unpack_p);
 }
 
 /**
@@ -453,16 +487,33 @@ unpack_string(std::string &value) {
   }
 }
 
+/**
+ * Unpacks the current numeric or string value from the stream.
+ */
+INLINE void DCPacker::
+unpack_blob(vector_uchar &value) {
+  nassertv(_mode == M_unpack);
+  if (_current_field == nullptr) {
+    _pack_error = true;
+
+  } else {
+    _current_field->unpack_blob(_unpack_data, _unpack_length, _unpack_p,
+                                value, _pack_error, _range_error);
+    advance();
+  }
+}
+
 /**
  * Returns the literal string that represents the packed value of the current
  * field, and advances the field pointer.
  */
 INLINE void DCPacker::
-unpack_literal_value(std::string &value) {
+unpack_literal_value(vector_uchar &value) {
   size_t start = _unpack_p;
   unpack_skip();
   nassertv(_unpack_p >= start);
-  value.assign(_unpack_data + start, _unpack_p - start);
+  value = vector_uchar((const unsigned char *)_unpack_data + start,
+                       (const unsigned char *)_unpack_data + _unpack_p);
 }
 
 /**
@@ -541,6 +592,15 @@ get_string() const {
   return _pack_data.get_string();
 }
 
+/**
+ * Returns the packed data buffer as a bytes object.  Also see get_data().
+ */
+INLINE vector_uchar DCPacker::
+get_bytes() const {
+  const unsigned char *p = (const unsigned char *)_pack_data.get_data();
+  return vector_uchar(p, p + _pack_data.get_length());
+}
+
 /**
  * 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
@@ -601,9 +661,9 @@ take_data() {
  * between packing sessions.
  */
 INLINE void DCPacker::
-append_data(const char *buffer, size_t size) {
+append_data(const unsigned char *buffer, size_t size) {
   nassertv(_mode == M_idle);
-  _pack_data.append_data(buffer, size);
+  _pack_data.append_data((const char *)buffer, size);
 }
 
 /**
@@ -728,6 +788,16 @@ raw_pack_string(const std::string &value) {
   _pack_data.append_data(value.data(), value.length());
 }
 
+/**
+ * Packs the data into the buffer between packing sessions.
+ */
+INLINE void DCPacker::
+raw_pack_blob(const vector_uchar &value) {
+  nassertv(_mode == M_idle);
+  DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value.size());
+  _pack_data.append_data((const char *)value.data(), value.size());
+}
+
 /**
  * Unpacks the data from the buffer between unpacking sessions.
  */
@@ -870,6 +940,16 @@ raw_unpack_string() {
   return value;
 }
 
+/**
+ * Unpacks the data from the buffer between unpacking sessions.
+ */
+INLINE vector_uchar DCPacker::
+raw_unpack_blob() {
+  vector_uchar value;
+  raw_unpack_blob(value);
+  return value;
+}
+
 /**
  * Unpacks the data from the buffer between unpacking sessions.
  */
@@ -971,6 +1051,24 @@ raw_unpack_string(std::string &value) {
   _unpack_p += string_length;
 }
 
+/**
+ * Unpacks the data from the buffer between unpacking sessions.
+ */
+INLINE void DCPacker::
+raw_unpack_blob(vector_uchar &value) {
+  nassertv(_mode == M_idle && _unpack_data != nullptr);
+  unsigned int blob_size = raw_unpack_uint16();
+
+  if (_unpack_p + blob_size > _unpack_length) {
+    _pack_error = true;
+    return;
+  }
+
+  const unsigned char *p = (const unsigned char *)_unpack_data + _unpack_p;
+  value = vector_uchar(p, p + blob_size);
+  _unpack_p += blob_size;
+}
+
 /**
  * Advances to the next field after a call to pack_value() or pop().
  */

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

@@ -114,12 +114,12 @@ end_pack() {
  * version of begin_unpack() that takes only one parameter.
  */
 void DCPacker::
-set_unpack_data(const string &data) {
+set_unpack_data(const vector_uchar &data) {
   nassertv(_mode == M_idle);
 
-  char *buffer = new char[data.length()];
-  memcpy(buffer, data.data(), data.length());
-  set_unpack_data(buffer, data.length(), true);
+  char *buffer = new char[data.size()];
+  memcpy(buffer, data.data(), data.size());
+  set_unpack_data(buffer, data.size(), true);
 }
 
 /**
@@ -721,11 +721,11 @@ pack_object(PyObject *object) {
       pack_string(string(buffer, length));
     }
   } else if (PyBytes_Check(object)) {
-    char *buffer;
+    const unsigned char *buffer;
     Py_ssize_t length;
-    PyBytes_AsStringAndSize(object, &buffer, &length);
+    PyBytes_AsStringAndSize(object, (char **)&buffer, &length);
     if (buffer) {
-      pack_string(string(buffer, length));
+      pack_blob(vector_uchar(buffer, buffer + length));
     }
 #else
   } else if (PyString_Check(object) || PyUnicode_Check(object)) {
@@ -1118,9 +1118,9 @@ enquote_string(ostream &out, char quote_mark, const string &str) {
  * Outputs the indicated string as a hex constant.
  */
 void DCPacker::
-output_hex_string(ostream &out, const string &str) {
+output_hex_string(ostream &out, const vector_uchar &str) {
   out << '<';
-  for (string::const_iterator pi = str.begin();
+  for (vector_uchar::const_iterator pi = str.begin();
        pi != str.end();
        ++pi) {
     char buffer[10];

+ 13 - 6
direct/src/dcparser/dcPacker.h

@@ -41,7 +41,7 @@ PUBLISHED:
   void begin_pack(const DCPackerInterface *root);
   bool end_pack();
 
-  void set_unpack_data(const std::string &data);
+  void set_unpack_data(const vector_uchar &data);
 public:
   void set_unpack_data(const char *unpack_data, size_t unpack_length,
                        bool owns_unpack_data);
@@ -75,7 +75,8 @@ PUBLISHED:
   INLINE void pack_int64(int64_t value);
   INLINE void pack_uint64(uint64_t value);
   INLINE void pack_string(const std::string &value);
-  INLINE void pack_literal_value(const std::string &value);
+  INLINE void pack_blob(const vector_uchar &value);
+  INLINE void pack_literal_value(const vector_uchar &value);
   void pack_default_value();
 
   INLINE double unpack_double();
@@ -84,7 +85,8 @@ PUBLISHED:
   INLINE int64_t unpack_int64();
   INLINE uint64_t unpack_uint64();
   INLINE std::string unpack_string();
-  INLINE std::string unpack_literal_value();
+  INLINE vector_uchar unpack_blob();
+  INLINE vector_uchar unpack_literal_value();
   void unpack_validate();
   void unpack_skip();
 
@@ -97,7 +99,8 @@ public:
   INLINE void unpack_int64(int64_t &value);
   INLINE void unpack_uint64(uint64_t &value);
   INLINE void unpack_string(std::string &value);
-  INLINE void unpack_literal_value(std::string &value);
+  INLINE void unpack_blob(vector_uchar &value);
+  INLINE void unpack_literal_value(vector_uchar &value);
 
 PUBLISHED:
 
@@ -119,6 +122,7 @@ PUBLISHED:
 
   INLINE size_t get_length() const;
   INLINE std::string get_string() const;
+  INLINE vector_uchar get_bytes() const;
   INLINE size_t get_unpack_length() const;
   INLINE std::string get_unpack_string() const;
 public:
@@ -126,7 +130,7 @@ public:
   INLINE const char *get_data() const;
   INLINE char *take_data();
 
-  INLINE void append_data(const char *buffer, size_t size);
+  INLINE void append_data(const unsigned char *buffer, size_t size);
   INLINE char *get_write_pointer(size_t size);
 
   INLINE const char *get_unpack_data() const;
@@ -148,6 +152,7 @@ PUBLISHED:
   INLINE void raw_pack_uint64(uint64_t value);
   INLINE void raw_pack_float64(double value);
   INLINE void raw_pack_string(const std::string &value);
+  INLINE void raw_pack_blob(const vector_uchar &value);
 
 // this is a hack to allw me to get in and out of 32bit Mode Faster need to
 // agree with channel_type in dcbase.h
@@ -165,6 +170,7 @@ PUBLISHED:
   INLINE uint64_t raw_unpack_uint64();
   INLINE double raw_unpack_float64();
   INLINE std::string raw_unpack_string();
+  INLINE vector_uchar raw_unpack_blob();
 
 public:
   INLINE void raw_unpack_int8(int &value);
@@ -177,10 +183,11 @@ public:
   INLINE void raw_unpack_uint64(uint64_t &value);
   INLINE void raw_unpack_float64(double &value);
   INLINE void raw_unpack_string(std::string &value);
+  INLINE void raw_unpack_blob(vector_uchar &value);
 
 public:
   static void enquote_string(std::ostream &out, char quote_mark, const std::string &str);
-  static void output_hex_string(std::ostream &out, const std::string &str);
+  static void output_hex_string(std::ostream &out, const vector_uchar &str);
 
 private:
   INLINE void advance();

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

@@ -248,6 +248,14 @@ pack_string(DCPackData &, const string &, bool &pack_error, bool &) const {
   pack_error = true;
 }
 
+/**
+ * Packs the indicated numeric or string value into the stream.
+ */
+void DCPackerInterface::
+pack_blob(DCPackData &, const vector_uchar &, bool &pack_error, bool &) const {
+  pack_error = true;
+}
+
 /**
  * Packs the field's specified default value (or a sensible default if no
  * value is specified) into the stream.  Returns true if the default value is
@@ -306,6 +314,14 @@ unpack_string(const char *, size_t, size_t &, string &, bool &pack_error, bool &
   pack_error = true;
 }
 
+/**
+ * Unpacks the current numeric or string value from the stream.
+ */
+void DCPackerInterface::
+unpack_blob(const char *, size_t, size_t &, vector_uchar &, bool &pack_error, bool &) const {
+  pack_error = true;
+}
+
 /**
  * Internally unpacks the current numeric or string value and validates it
  * against the type range limits, but does not return the value.  Returns true

+ 7 - 2
direct/src/dcparser/dcPackerInterface.h

@@ -16,6 +16,7 @@
 
 #include "dcbase.h"
 #include "dcSubatomicType.h"
+#include "vector_uchar.h"
 
 class DCFile;
 class DCField;
@@ -37,8 +38,8 @@ enum DCPackType {
 
   // These PackTypes are all fundamental types, and should be packed (or
   // unpacked) with the corresponding call to pack_double(), pack_int(), etc.
-  // PT_blob is the same as PT_string, but implies that the string contains
-  // binary data.
+  // PT_blob is similar to PT_string, except that it contains arbitrary binary
+  // data instead of just UTF-8 text.
   PT_double,
   PT_int,
   PT_uint,
@@ -113,6 +114,8 @@ public:
                            bool &pack_error, bool &range_error) const;
   virtual void pack_string(DCPackData &pack_data, const std::string &value,
                            bool &pack_error, bool &range_error) const;
+  virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value,
+                         bool &pack_error, bool &range_error) const;
   virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
   virtual void unpack_double(const char *data, size_t length, size_t &p,
@@ -127,6 +130,8 @@ public:
                              uint64_t &value, bool &pack_error, bool &range_error) const;
   virtual void unpack_string(const char *data, size_t length, size_t &p,
                              std::string &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_blob(const char *data, size_t length, size_t &p,
+                           vector_uchar &value, bool &pack_error, bool &range_error) const;
   virtual bool unpack_validate(const char *data, size_t length, size_t &p,
                                bool &pack_error, bool &range_error) const;
   virtual bool unpack_skip(const char *data, size_t length, size_t &p,

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


+ 66 - 63
direct/src/dcparser/dcParser.h.prebuilt

@@ -1,20 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.4.2.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
 
-/* Skeleton interface for Bison's Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
-   Foundation, Inc.
-   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -27,66 +26,74 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+#ifndef YY_DCYY_BUILT_TMP_DCPARSER_YXX_H_INCLUDED
+# define YY_DCYY_BUILT_TMP_DCPARSER_YXX_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int dcyydebug;
+#endif
 
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     UNSIGNED_INTEGER = 258,
-     SIGNED_INTEGER = 259,
-     REAL = 260,
-     STRING = 261,
-     HEX_STRING = 262,
-     IDENTIFIER = 263,
-     KEYWORD = 264,
-     KW_DCLASS = 265,
-     KW_STRUCT = 266,
-     KW_FROM = 267,
-     KW_IMPORT = 268,
-     KW_TYPEDEF = 269,
-     KW_KEYWORD = 270,
-     KW_SWITCH = 271,
-     KW_CASE = 272,
-     KW_DEFAULT = 273,
-     KW_BREAK = 274,
-     KW_INT8 = 275,
-     KW_INT16 = 276,
-     KW_INT32 = 277,
-     KW_INT64 = 278,
-     KW_UINT8 = 279,
-     KW_UINT16 = 280,
-     KW_UINT32 = 281,
-     KW_UINT64 = 282,
-     KW_FLOAT64 = 283,
-     KW_STRING = 284,
-     KW_BLOB = 285,
-     KW_BLOB32 = 286,
-     KW_INT8ARRAY = 287,
-     KW_INT16ARRAY = 288,
-     KW_INT32ARRAY = 289,
-     KW_UINT8ARRAY = 290,
-     KW_UINT16ARRAY = 291,
-     KW_UINT32ARRAY = 292,
-     KW_UINT32UINT8ARRAY = 293,
-     KW_CHAR = 294,
-     START_DC = 295,
-     START_PARAMETER_VALUE = 296,
-     START_PARAMETER_DESCRIPTION = 297
-   };
+  enum yytokentype
+  {
+    UNSIGNED_INTEGER = 258,
+    SIGNED_INTEGER = 259,
+    REAL = 260,
+    STRING = 261,
+    IDENTIFIER = 262,
+    HEX_STRING = 263,
+    KEYWORD = 264,
+    KW_DCLASS = 265,
+    KW_STRUCT = 266,
+    KW_FROM = 267,
+    KW_IMPORT = 268,
+    KW_TYPEDEF = 269,
+    KW_KEYWORD = 270,
+    KW_SWITCH = 271,
+    KW_CASE = 272,
+    KW_DEFAULT = 273,
+    KW_BREAK = 274,
+    KW_INT8 = 275,
+    KW_INT16 = 276,
+    KW_INT32 = 277,
+    KW_INT64 = 278,
+    KW_UINT8 = 279,
+    KW_UINT16 = 280,
+    KW_UINT32 = 281,
+    KW_UINT64 = 282,
+    KW_FLOAT64 = 283,
+    KW_STRING = 284,
+    KW_BLOB = 285,
+    KW_BLOB32 = 286,
+    KW_INT8ARRAY = 287,
+    KW_INT16ARRAY = 288,
+    KW_INT32ARRAY = 289,
+    KW_UINT8ARRAY = 290,
+    KW_UINT16ARRAY = 291,
+    KW_UINT32ARRAY = 292,
+    KW_UINT32UINT8ARRAY = 293,
+    KW_CHAR = 294,
+    START_DC = 295,
+    START_PARAMETER_VALUE = 296,
+    START_PARAMETER_DESCRIPTION = 297
+  };
 #endif
 /* Tokens.  */
 #define UNSIGNED_INTEGER 258
 #define SIGNED_INTEGER 259
 #define REAL 260
 #define STRING 261
-#define HEX_STRING 262
-#define IDENTIFIER 263
+#define IDENTIFIER 262
+#define HEX_STRING 263
 #define KEYWORD 264
 #define KW_DCLASS 265
 #define KW_STRUCT 266
@@ -122,15 +129,11 @@
 #define START_PARAMETER_VALUE 296
 #define START_PARAMETER_DESCRIPTION 297
 
+/* Value type.  */
 
 
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
 extern YYSTYPE dcyylval;
 
+int dcyyparse (void);
 
+#endif /* !YY_DCYY_BUILT_TMP_DCPARSER_YXX_H_INCLUDED  */

+ 28 - 27
direct/src/dcparser/dcParser.yxx

@@ -57,7 +57,7 @@ dc_init_parser(istream &in, const string &filename, DCFile &file) {
 }
 
 void
-dc_init_parser_parameter_value(istream &in, const string &filename, 
+dc_init_parser_parameter_value(istream &in, const string &filename,
                                DCPacker &packer) {
   dc_file = nullptr;
   current_packer = &packer;
@@ -89,15 +89,16 @@ dc_cleanup_parser() {
 %token <u.uint64> UNSIGNED_INTEGER
 %token <u.int64> SIGNED_INTEGER
 %token <u.real> REAL
-%token <str> STRING HEX_STRING IDENTIFIER
+%token <str> STRING IDENTIFIER
+%token <bytes> HEX_STRING
 %token <u.keyword> KEYWORD
 
-%token KW_DCLASS 
-%token KW_STRUCT 
-%token KW_FROM 
-%token KW_IMPORT 
-%token KW_TYPEDEF 
-%token KW_KEYWORD 
+%token KW_DCLASS
+%token KW_STRUCT
+%token KW_FROM
+%token KW_IMPORT
+%token KW_TYPEDEF
+%token KW_KEYWORD
 %token KW_SWITCH
 %token KW_CASE
 %token KW_DEFAULT
@@ -224,7 +225,7 @@ import:
 {
   dc_file->add_import_module($2);
 }
-        | KW_FROM import_identifier KW_IMPORT 
+        | KW_FROM import_identifier KW_IMPORT
 {
   dc_file->add_import_module($2);
 }
@@ -255,7 +256,7 @@ typedef_decl:
 {
   if ($2 != nullptr) {
     DCTypedef *dtypedef = new DCTypedef($2);
-    
+
     if (!dc_file->add_typedef(dtypedef)) {
       DCTypedef *old_typedef = dc_file->get_typedef_by_name(dtypedef->get_name());
       if (old_typedef->is_bogus_typedef()) {
@@ -294,7 +295,7 @@ dclass_or_struct:
         ;
 
 dclass:
-        KW_DCLASS optional_name 
+        KW_DCLASS optional_name
 {
   current_class = new DCClass(dc_file, $2, false, false);
 }
@@ -322,7 +323,7 @@ dclass_name:
     if (dclass->is_struct()) {
       yyerror("struct name not allowed");
     }
-  
+
     $$ = dclass;
   }
 }
@@ -398,7 +399,7 @@ dclass_field:
         ;
 
 struct:
-        KW_STRUCT optional_name 
+        KW_STRUCT optional_name
 {
   current_class = new DCClass(dc_file, $2, true, false);
 }
@@ -426,7 +427,7 @@ struct_name:
     if (!dstruct->is_struct()) {
       yyerror("struct name required");
     }
-  
+
     $$ = dstruct;
   }
 }
@@ -538,7 +539,7 @@ unnamed_parameter:
 
 named_parameter_with_default:
         named_parameter
-        | named_parameter '=' 
+        | named_parameter '='
 {
   current_packer = &default_packer;
   current_packer->clear_data();
@@ -553,7 +554,7 @@ named_parameter_with_default:
     is_valid = $1->is_valid();
   }
   if (current_packer->end_pack()) {
-    $1->set_default_value(current_packer->get_string());
+    $1->set_default_value(current_packer->get_bytes());
 
   } else {
     if (is_valid) {
@@ -568,7 +569,7 @@ named_parameter_with_default:
 
 unnamed_parameter_with_default:
         unnamed_parameter
-        | unnamed_parameter '=' 
+        | unnamed_parameter '='
 {
   current_packer = &default_packer;
   current_packer->clear_data();
@@ -583,7 +584,7 @@ unnamed_parameter_with_default:
     is_valid = $1->is_valid();
   }
   if (current_packer->end_pack()) {
-    $1->set_default_value(current_packer->get_string());
+    $1->set_default_value(current_packer->get_bytes());
 
   } else {
     if (is_valid) {
@@ -663,7 +664,7 @@ simple_type_name:
   $$ = simple_param;
 }
         | simple_type_name '%' number
-{ 
+{
   DCSimpleParameter *simple_param = $1->as_simple_parameter();
   nassertr(simple_param != nullptr, 0);
   if (!simple_param->is_numeric_type()) {
@@ -703,10 +704,10 @@ type_name:
           dtypedef = new DCTypedef($1);
         }
       }
-      
+
       dc_file->add_typedef(dtypedef);
     }
-    
+
     $$ = dtypedef->make_new_parameter();
   }
 }
@@ -974,7 +975,7 @@ parameter_value:
 {
   if ($1 != current_packer->get_current_field_name()) {
     ostringstream strm;
-    strm << "Got '" << $1 << "', expected '" 
+    strm << "Got '" << $1 << "', expected '"
          << current_packer->get_current_field_name() << "'";
     yyerror(strm.str());
   }
@@ -1005,7 +1006,7 @@ parameter_actual_value:
 {
   current_packer->pack_literal_value($1);
 }
-        | '{' 
+        | '{'
 {
   current_packer->push();
 }
@@ -1013,7 +1014,7 @@ parameter_actual_value:
 {
   current_packer->pop();
 }
-        | '[' 
+        | '['
 {
   current_packer->push();
 }
@@ -1021,7 +1022,7 @@ parameter_actual_value:
 {
   current_packer->pop();
 }
-        | '(' 
+        | '('
 {
   current_packer->push();
 }
@@ -1223,7 +1224,7 @@ molecular_atom_list:
   if ($3 != nullptr) {
     current_molecular->add_atomic($3);
     if (!$3->is_bogus_field() && !current_molecular->compare_keywords(*$3)) {
-      yyerror("Mismatched keywords in molecule between " + 
+      yyerror("Mismatched keywords in molecule between " +
               current_molecular->get_atomic(0)->get_name() + " and " +
               $3->get_name());
     }
@@ -1283,7 +1284,7 @@ switch_case:
     yyerror("Invalid value for switch parameter");
     current_switch->add_invalid_case();
   } else {
-    int case_index = current_switch->add_case(current_packer->get_string());
+    int case_index = current_switch->add_case(current_packer->get_bytes());
     if (case_index == -1) {
       yyerror("Duplicate case value");
     }

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

@@ -16,6 +16,7 @@
 
 #include "dcbase.h"
 #include "dcSubatomicType.h"
+#include "vector_uchar.h"
 
 class DCFile;
 class DCClass;
@@ -61,6 +62,7 @@ public:
     const DCKeyword *keyword;
   } u;
   std::string str;
+  vector_uchar bytes;
 };
 
 // The yacc-generated code expects to use the symbol 'YYSTYPE' to refer to the

+ 119 - 0
direct/src/dcparser/dcSimpleParameter.cxx

@@ -1069,6 +1069,52 @@ pack_string(DCPackData &pack_data, const string &value,
   }
 }
 
+/**
+ * Packs the indicated numeric or string value into the stream.
+ */
+void DCSimpleParameter::
+pack_blob(DCPackData &pack_data, const vector_uchar &value,
+          bool &pack_error, bool &range_error) const {
+  size_t blob_size = value.size();
+
+  switch (_type) {
+  case ST_char:
+  case ST_uint8:
+  case ST_int8:
+    if (blob_size == 0) {
+      pack_error = true;
+    } else {
+      if (blob_size != 1) {
+        range_error = true;
+      }
+      _uint_range.validate((unsigned int)value[0], range_error);
+      do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)value[0]);
+    }
+    break;
+
+  case ST_string:
+  case ST_blob:
+    _uint_range.validate(blob_size, range_error);
+    validate_uint_limits(blob_size, 16, range_error);
+    if (_num_length_bytes != 0) {
+      do_pack_uint16(pack_data.get_write_pointer(2), blob_size);
+    }
+    pack_data.append_data((const char *)value.data(), blob_size);
+    break;
+
+  case ST_blob32:
+    _uint_range.validate(blob_size, range_error);
+    if (_num_length_bytes != 0) {
+      do_pack_uint32(pack_data.get_write_pointer(4), blob_size);
+    }
+    pack_data.append_data((const char *)value.data(), blob_size);
+    break;
+
+  default:
+    pack_error = true;
+  }
+}
+
 /**
  * Packs the simpleParameter's specified default value (or a sensible default
  * if no value is specified) into the stream.  Returns true if the default
@@ -1937,6 +1983,79 @@ unpack_string(const char *data, size_t length, size_t &p, string &value,
   return;
 }
 
+/**
+ * Unpacks the current numeric or string value from the stream.
+ */
+void DCSimpleParameter::
+unpack_blob(const char *data, size_t length, size_t &p, vector_uchar &value,
+            bool &pack_error, bool &range_error) const {
+  // If the type is a single byte, unpack it into a string of length 1.
+  switch (_type) {
+  case ST_char:
+  case ST_int8:
+  case ST_uint8:
+    {
+      if (p + 1 > length) {
+        pack_error = true;
+        return;
+      }
+      unsigned int int_value = do_unpack_uint8(data + p);
+      _uint_range.validate(int_value, range_error);
+      value.resize(1);
+      value[0] = int_value;
+      p++;
+    }
+    return;
+
+  default:
+    break;
+  }
+
+  size_t blob_size;
+
+  if (_num_length_bytes == 0) {
+    blob_size = _fixed_byte_size;
+
+  } else {
+    switch (_type) {
+    case ST_string:
+    case ST_blob:
+      if (p + 2 > length) {
+        pack_error = true;
+        return;
+      }
+      blob_size = do_unpack_uint16(data + p);
+      p += 2;
+      break;
+
+    case ST_blob32:
+      if (p + 4 > length) {
+        pack_error = true;
+        return;
+      }
+      blob_size = do_unpack_uint32(data + p);
+      p += 4;
+      break;
+
+    default:
+      pack_error = true;
+      return;
+    }
+  }
+
+  _uint_range.validate(blob_size, range_error);
+
+  if (p + blob_size > length) {
+    pack_error = true;
+    return;
+  }
+  value = vector_uchar((const unsigned char *)data + p,
+                       (const unsigned char *)data + p + blob_size);
+  p += blob_size;
+
+  return;
+}
+
 /**
  * Internally unpacks the current numeric or string value and validates it
  * against the type range limits, but does not return the value.  Returns true

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

@@ -62,6 +62,8 @@ public:
                            bool &pack_error, bool &range_error) const;
   virtual void pack_string(DCPackData &pack_data, const std::string &value,
                            bool &pack_error, bool &range_error) const;
+  virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value,
+                         bool &pack_error, bool &range_error) const;
   virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
   virtual void unpack_double(const char *data, size_t length, size_t &p,
@@ -76,6 +78,8 @@ public:
                              uint64_t &value, bool &pack_error, bool &range_error) const;
   virtual void unpack_string(const char *data, size_t length, size_t &p,
                              std::string &value, bool &pack_error, bool &range_error) const;
+  virtual void unpack_blob(const char *data, size_t length, size_t &p,
+                           vector_uchar &value, bool &pack_error, bool &range_error) const;
   virtual bool unpack_validate(const char *data, size_t length, size_t &p,
                                bool &pack_error, bool &range_error) const;
   virtual bool unpack_skip(const char *data, size_t length, size_t &p,

+ 8 - 7
direct/src/dcparser/dcSwitch.cxx

@@ -109,7 +109,7 @@ get_num_cases() const {
  * if no case has this value.
  */
 int DCSwitch::
-get_case_by_value(const string &case_value) const {
+get_case_by_value(const vector_uchar &case_value) const {
   CasesByValue::const_iterator vi;
   vi = _cases_by_value.find(case_value);
   if (vi != _cases_by_value.end()) {
@@ -140,9 +140,9 @@ get_default_case() const {
 /**
  * Returns the packed value associated with the indicated case.
  */
-string DCSwitch::
+vector_uchar DCSwitch::
 get_value(int case_index) const {
-  nassertr(case_index >= 0 && case_index < (int)_cases.size(), string());
+  nassertr(case_index >= 0 && case_index < (int)_cases.size(), vector_uchar());
   return _cases[case_index]->_value;
 }
 
@@ -198,7 +198,7 @@ is_field_valid() const {
  * -1. This is normally called only by the parser.
  */
 int DCSwitch::
-add_case(const string &value) {
+add_case(const vector_uchar &value) {
   int case_index = (int)_cases.size();
   if (!_cases_by_value.insert(CasesByValue::value_type(value, case_index)).second) {
     add_invalid_case();
@@ -283,7 +283,8 @@ add_break() {
 const DCPackerInterface *DCSwitch::
 apply_switch(const char *value_data, size_t length) const {
   CasesByValue::const_iterator vi;
-  vi = _cases_by_value.find(string(value_data, length));
+  vi = _cases_by_value.find(vector_uchar((const unsigned char *)value_data,
+                                         (const unsigned char *)value_data + length));
   if (vi != _cases_by_value.end()) {
     return _cases[(*vi).second]->_fields;
   }
@@ -421,7 +422,7 @@ generate_hash(HashGenerator &hashgen) const {
   Cases::const_iterator ci;
   for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
     const SwitchCase *dcase = (*ci);
-    hashgen.add_string(dcase->_value);
+    hashgen.add_blob(dcase->_value);
 
     const SwitchFields *fields = dcase->_fields;
     hashgen.add_int(fields->_fields.size());
@@ -702,7 +703,7 @@ do_check_match(const DCPackerInterface *) const {
  *
  */
 DCSwitch::SwitchCase::
-SwitchCase(const string &value, DCSwitch::SwitchFields *fields) :
+SwitchCase(const vector_uchar &value, DCSwitch::SwitchFields *fields) :
   _value(value),
   _fields(fields)
 {

+ 6 - 6
direct/src/dcparser/dcSwitch.h

@@ -40,18 +40,18 @@ PUBLISHED:
   DCField *get_key_parameter() const;
 
   int get_num_cases() const;
-  int get_case_by_value(const std::string &case_value) const;
+  int get_case_by_value(const vector_uchar &case_value) const;
   DCPackerInterface *get_case(int n) const;
   DCPackerInterface *get_default_case() const;
 
-  std::string get_value(int case_index) const;
+  vector_uchar get_value(int case_index) const;
   int get_num_fields(int case_index) const;
   DCField *get_field(int case_index, int n) const;
   DCField *get_field_by_name(int case_index, const std::string &name) const;
 
 public:
   bool is_field_valid() const;
-  int add_case(const std::string &value);
+  int add_case(const vector_uchar &value);
   void add_invalid_case();
   bool add_default();
   bool add_field(DCField *field);
@@ -98,13 +98,13 @@ public:
 
   class SwitchCase {
   public:
-    SwitchCase(const std::string &value, SwitchFields *fields);
+    SwitchCase(const vector_uchar &value, SwitchFields *fields);
     ~SwitchCase();
 
     bool do_check_match_switch_case(const SwitchCase *other) const;
 
   public:
-    std::string _value;
+    vector_uchar _value;
     SwitchFields *_fields;
   };
 
@@ -137,7 +137,7 @@ private:
   bool _fields_added;
 
   // This map indexes into the _cases vector, above.
-  typedef pmap<std::string, int> CasesByValue;
+  typedef pmap<vector_uchar, int> CasesByValue;
   CasesByValue _cases_by_value;
 };
 

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

@@ -56,6 +56,18 @@ add_string(const std::string &str) {
   }
 }
 
+/**
+ * Adds a blob to the hash, by breaking it down into a sequence of integers.
+ */
+void HashGenerator::
+add_blob(const vector_uchar &bytes) {
+  add_int(bytes.size());
+  vector_uchar::const_iterator bi;
+  for (bi = bytes.begin(); bi != bytes.end(); ++bi) {
+    add_int(*bi);
+  }
+}
+
 /**
  * Returns the hash number generated.
  */

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

@@ -16,6 +16,7 @@
 
 #include "dcbase.h"
 #include "primeNumberGenerator.h"
+#include "vector_uchar.h"
 
 /**
  * This class generates an arbitrary hash number from a sequence of ints.
@@ -26,6 +27,7 @@ public:
 
   void add_int(int num);
   void add_string(const std::string &str);
+  void add_blob(const vector_uchar &bytes);
 
   unsigned long get_hash() const;
 

+ 1 - 1
direct/src/distributed/cConnectionRepository.cxx

@@ -891,7 +891,7 @@ describe_message(std::ostream &out, const string &prefix,
                  const Datagram &dg) const {
   DCPacker packer;
 
-  packer.set_unpack_data(dg.get_message());
+  packer.set_unpack_data((const char *)dg.get_data(), dg.get_length(), false);
   CHANNEL_TYPE do_id;
   int msg_type;
   bool is_update = false;

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