Forráskód Böngészése

Interrogate wraps vector<unsigned char> as Python 3 bytes object

rdb 9 éve
szülő
commit
5543716660

+ 0 - 1
dtool/src/dtoolbase/dtoolbase.h

@@ -416,7 +416,6 @@ typedef struct _object PyObject;
 #define MAKE_PROPERTY2(property_name, ...) __make_property2(property_name, __VA_ARGS__)
 #define MAKE_PROPERTY2(property_name, ...) __make_property2(property_name, __VA_ARGS__)
 #define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
 #define MAKE_SEQ(seq_name, num_name, element_name) __make_seq(seq_name, num_name, element_name)
 #define MAKE_SEQ_PROPERTY(property_name, ...) __make_seq_property(property_name, __VA_ARGS__)
 #define MAKE_SEQ_PROPERTY(property_name, ...) __make_seq_property(property_name, __VA_ARGS__)
-#undef USE_STL_ALLOCATOR  /* Don't try to parse these template classes in interrogate. */
 #define EXTENSION(x) __extension x
 #define EXTENSION(x) __extension x
 #define EXTEND __extension
 #define EXTEND __extension
 #else
 #else

+ 1 - 1
dtool/src/dtoolbase/pallocator.h

@@ -32,7 +32,7 @@
  * can allocate arrays of objects.
  * can allocate arrays of objects.
  */
  */
 
 
-#ifndef USE_STL_ALLOCATOR
+#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER)
 // If we're not trying to make custom allocators (either we don't know what
 // If we're not trying to make custom allocators (either we don't know what
 // kind of syntax this STL library wants, or we're compiling with OPTIMIZE 4),
 // kind of syntax this STL library wants, or we're compiling with OPTIMIZE 4),
 // then simply use the standard allocator.
 // then simply use the standard allocator.

+ 1 - 1
dtool/src/dtoolbase/pdeque.h

@@ -19,7 +19,7 @@
 #include "register_type.h"
 #include "register_type.h"
 #include <deque>
 #include <deque>
 
 
-#ifndef USE_STL_ALLOCATOR
+#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER)
 // If we're not using custom allocators, just use the standard class
 // If we're not using custom allocators, just use the standard class
 // definition.
 // definition.
 #define pdeque deque
 #define pdeque deque

+ 1 - 1
dtool/src/dtoolbase/plist.h

@@ -19,7 +19,7 @@
 #include "register_type.h"
 #include "register_type.h"
 #include <list>
 #include <list>
 
 
-#ifndef USE_STL_ALLOCATOR
+#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER)
 // If we're not using custom allocators, just use the standard class
 // If we're not using custom allocators, just use the standard class
 // definition.
 // definition.
 #define plist list
 #define plist list

+ 1 - 1
dtool/src/dtoolbase/pmap.h

@@ -24,7 +24,7 @@
 #include <hash_map>
 #include <hash_map>
 #endif
 #endif
 
 
-#ifndef USE_STL_ALLOCATOR
+#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER)
 // If we're not using custom allocators, just use the standard class
 // If we're not using custom allocators, just use the standard class
 // definition.
 // definition.
 #define pmap map
 #define pmap map

+ 1 - 1
dtool/src/dtoolbase/pset.h

@@ -24,7 +24,7 @@
 #include <hash_set>
 #include <hash_set>
 #endif
 #endif
 
 
-#ifndef USE_STL_ALLOCATOR
+#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER)
 // If we're not using custom allocators, just use the standard class
 // If we're not using custom allocators, just use the standard class
 // definition.
 // definition.
 #define pset set
 #define pset set

+ 6 - 0
dtool/src/dtoolbase/pvector.h

@@ -25,6 +25,12 @@
 // definition.
 // definition.
 #define pvector vector
 #define pvector vector
 
 
+#elif defined(CPPPARSER)
+// Simplified definition to speed up Interrogate parsing.
+template<class Type>
+class pvector : public vector<Type> {
+};
+
 #else
 #else
 
 
 /**
 /**

+ 12 - 0
dtool/src/interrogate/interfaceMaker.cxx

@@ -361,6 +361,18 @@ remap_parameter(CPPType *struct_type, CPPType *param_type) {
         }
         }
       }
       }
     }
     }
+    if (struct_type == (CPPType *)NULL ||
+        !TypeManager::is_vector_unsigned_char(struct_type)) {
+      if (TypeManager::is_vector_unsigned_char(param_type)) {
+        if (TypeManager::is_reference(param_type)) {
+          return new ParameterRemapReferenceToConcrete(param_type);
+        } else if (TypeManager::is_const(param_type)) {
+          return new ParameterRemapConstToNonConst(param_type);
+        } else {
+          return new ParameterRemapUnchanged(param_type);
+        }
+      }
+    }
   }
   }
 
 
   if (manage_reference_counts) {
   if (manage_reference_counts) {

+ 24 - 1
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -4794,6 +4794,26 @@ write_function_instance(ostream &out, FunctionRemap *remap,
       clear_error = true;
       clear_error = true;
       only_pyobjects = false;
       only_pyobjects = false;
 
 
+    } else if (TypeManager::is_vector_unsigned_char(type)) {
+      indent(out, indent_level) << "unsigned char *" << param_name << "_str = NULL;\n";
+      indent(out, indent_level) << "Py_ssize_t " << param_name << "_len;\n";
+
+      if (args_type == AT_single_arg) {
+        extra_param_check << " && PyBytes_AsStringAndSize(arg, (char **)&"
+          << param_name << "_str, &" << param_name << "_len) >= 0";
+      } else {
+        format_specifiers += "\" FMTCHAR_BYTES \"#";
+        parameter_list += ", &" + param_name + "_str, &" + param_name + "_len";
+      }
+
+      pexpr_string = type->get_local_name(&parser);
+      pexpr_string += "(" + param_name + "_str, " + param_name + "_str + " + param_name + "_len" + ")";
+      expected_params += "bytes";
+
+      // Remember to clear the TypeError that any of the above methods raise.
+      clear_error = true;
+      only_pyobjects = false;
+
     } else if (TypeManager::is_bool(type)) {
     } else if (TypeManager::is_bool(type)) {
       if (args_type == AT_single_arg) {
       if (args_type == AT_single_arg) {
         param_name = "arg";
         param_name = "arg";
@@ -6072,7 +6092,8 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
       TypeManager::is_char_pointer(type) ||
       TypeManager::is_char_pointer(type) ||
       TypeManager::is_wchar_pointer(type) ||
       TypeManager::is_wchar_pointer(type) ||
       TypeManager::is_pointer_to_PyObject(type) ||
       TypeManager::is_pointer_to_PyObject(type) ||
-      TypeManager::is_pointer_to_Py_buffer(type)) {
+      TypeManager::is_pointer_to_Py_buffer(type) ||
+      TypeManager::is_vector_unsigned_char(type)) {
     // Most types are now handled by the many overloads of Dtool_WrapValue,
     // Most types are now handled by the many overloads of Dtool_WrapValue,
     // defined in py_panda.h.
     // defined in py_panda.h.
     indent(out, indent_level)
     indent(out, indent_level)
@@ -6713,6 +6734,8 @@ is_cpp_type_legal(CPPType *in_ctype) {
     return true;
     return true;
   } else if (TypeManager::is_basic_string_wchar(type)) {
   } else if (TypeManager::is_basic_string_wchar(type)) {
     return true;
     return true;
+  } else if (TypeManager::is_vector_unsigned_char(type)) {
+    return true;
   } else if (TypeManager::is_simple(type)) {
   } else if (TypeManager::is_simple(type)) {
     return true;
     return true;
   } else if (TypeManager::is_pointer_to_simple(type)) {
   } else if (TypeManager::is_pointer_to_simple(type)) {

+ 60 - 0
dtool/src/interrogate/typeManager.cxx

@@ -937,6 +937,66 @@ is_wstring(CPPType *type) {
   return is_basic_string_wchar(type);
   return is_basic_string_wchar(type);
 }
 }
 
 
+/**
+ * Returns true if the type is vector<unsigned char>, or a const reference to
+ * it.
+ */
+bool TypeManager::
+is_vector_unsigned_char(CPPType *type) {
+  if (type->get_local_name(&parser) == "vector< unsigned char >" ||
+      type->get_local_name(&parser) == "pvector< unsigned char >") {
+    return true;
+  }
+
+  switch (type->get_subtype()) {
+  case CPPDeclaration::ST_const:
+    return is_vector_unsigned_char(type->as_const_type()->_wrapped_around);
+
+  case CPPDeclaration::ST_reference:
+    return is_const_vector_unsigned_char(type->as_reference_type()->_pointing_at);
+
+  case CPPDeclaration::ST_struct:
+    {
+      CPPStructType *stype = type->as_struct_type();
+      CPPStructType::Derivation::const_iterator di;
+      for (di = stype->_derivation.begin();
+           di != stype->_derivation.end();
+           ++di) {
+        if (is_vector_unsigned_char((*di)._base)) {
+          return true;
+        }
+      }
+    }
+    break;
+
+  case CPPDeclaration::ST_typedef:
+    return is_vector_unsigned_char(type->as_typedef_type()->_type);
+
+  default:
+    break;
+  }
+
+  return false;
+}
+
+/**
+ * Returns true if the indicated type is a const wrapper around
+ * vector<unsigned char>.
+ */
+bool TypeManager::
+is_const_vector_unsigned_char(CPPType *type) {
+  switch (type->get_subtype()) {
+  case CPPDeclaration::ST_const:
+    return is_vector_unsigned_char(type->as_const_type()->_wrapped_around);
+
+  case CPPDeclaration::ST_typedef:
+    return is_const_vector_unsigned_char(type->as_typedef_type()->_type);
+
+  default:
+    return false;
+  }
+}
+
 /**
 /**
  * Returns true if the indicated type is bool, or some trivial variant.
  * Returns true if the indicated type is bool, or some trivial variant.
  */
  */

+ 2 - 0
dtool/src/interrogate/typeManager.h

@@ -81,6 +81,8 @@ public:
   static bool is_const_ref_to_basic_string_wchar(CPPType *type);
   static bool is_const_ref_to_basic_string_wchar(CPPType *type);
   static bool is_const_ptr_to_basic_string_wchar(CPPType *type);
   static bool is_const_ptr_to_basic_string_wchar(CPPType *type);
   static bool is_wstring(CPPType *type);
   static bool is_wstring(CPPType *type);
+  static bool is_vector_unsigned_char(CPPType *type);
+  static bool is_const_vector_unsigned_char(CPPType *type);
   static bool is_pair(CPPType *type);
   static bool is_pair(CPPType *type);
   static bool is_bool(CPPType *type);
   static bool is_bool(CPPType *type);
   static bool is_integer(CPPType *type);
   static bool is_integer(CPPType *type);

+ 7 - 0
dtool/src/interrogatedb/py_panda.h

@@ -128,6 +128,13 @@ typedef long Py_hash_t;
 #endif
 #endif
 #endif
 #endif
 
 
+// Which character to use in PyArg_ParseTuple et al for a byte string.
+#if PY_MAJOR_VERSION >= 3
+#define FMTCHAR_BYTES "y"
+#else
+#define FMTCHAR_BYTES "s"
+#endif
+
 using namespace std;
 using namespace std;
 
 
 // this is tempory .. untill this is glued better into the panda build system
 // this is tempory .. untill this is glued better into the panda build system

+ 10 - 0
panda/src/express/hashVal.I

@@ -184,6 +184,16 @@ INLINE void HashVal::
 hash_string(const string &data) {
 hash_string(const string &data) {
   hash_buffer(data.data(), data.length());
   hash_buffer(data.data(), data.length());
 }
 }
+
+/**
+ * Generates the hash value by hashing the indicated data.  This method is
+ * only defined if we have the OpenSSL library (which provides md5
+ * functionality) available.
+ */
+INLINE void HashVal::
+hash_bytes(const pvector<unsigned char> &data) {
+  hash_buffer((const char *)&data[0], data.size());
+}
 #endif  // HAVE_OPENSSL
 #endif  // HAVE_OPENSSL
 
 
 /**
 /**

+ 1 - 0
panda/src/express/hashVal.h

@@ -68,6 +68,7 @@ PUBLISHED:
   bool hash_stream(istream &stream);
   bool hash_stream(istream &stream);
   INLINE void hash_ramfile(const Ramfile &ramfile);
   INLINE void hash_ramfile(const Ramfile &ramfile);
   INLINE void hash_string(const string &data);
   INLINE void hash_string(const string &data);
+  INLINE void hash_bytes(const pvector<unsigned char> &data);
   void hash_buffer(const char *buffer, int length);
   void hash_buffer(const char *buffer, int length);
 #endif  // HAVE_OPENSSL
 #endif  // HAVE_OPENSSL