diff --git a/dtool/src/dtoolbase/dtoolbase.h b/dtool/src/dtoolbase/dtoolbase.h index e3c346d4a0..7ec1cb6f04 100644 --- a/dtool/src/dtoolbase/dtoolbase.h +++ b/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_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__) -#undef USE_STL_ALLOCATOR /* Don't try to parse these template classes in interrogate. */ #define EXTENSION(x) __extension x #define EXTEND __extension #else diff --git a/dtool/src/dtoolbase/pallocator.h b/dtool/src/dtoolbase/pallocator.h index 5c1c8d4d5d..deddc2abfc 100644 --- a/dtool/src/dtoolbase/pallocator.h +++ b/dtool/src/dtoolbase/pallocator.h @@ -32,7 +32,7 @@ * 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 // kind of syntax this STL library wants, or we're compiling with OPTIMIZE 4), // then simply use the standard allocator. diff --git a/dtool/src/dtoolbase/pdeque.h b/dtool/src/dtoolbase/pdeque.h index eca91125cf..245f7e299a 100644 --- a/dtool/src/dtoolbase/pdeque.h +++ b/dtool/src/dtoolbase/pdeque.h @@ -19,7 +19,7 @@ #include "register_type.h" #include -#ifndef USE_STL_ALLOCATOR +#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER) // If we're not using custom allocators, just use the standard class // definition. #define pdeque deque diff --git a/dtool/src/dtoolbase/plist.h b/dtool/src/dtoolbase/plist.h index c0ce518720..9effd8db6a 100644 --- a/dtool/src/dtoolbase/plist.h +++ b/dtool/src/dtoolbase/plist.h @@ -19,7 +19,7 @@ #include "register_type.h" #include -#ifndef USE_STL_ALLOCATOR +#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER) // If we're not using custom allocators, just use the standard class // definition. #define plist list diff --git a/dtool/src/dtoolbase/pmap.h b/dtool/src/dtoolbase/pmap.h index 08a9b1ec22..e9b318c36b 100644 --- a/dtool/src/dtoolbase/pmap.h +++ b/dtool/src/dtoolbase/pmap.h @@ -24,7 +24,7 @@ #include #endif -#ifndef USE_STL_ALLOCATOR +#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER) // If we're not using custom allocators, just use the standard class // definition. #define pmap map diff --git a/dtool/src/dtoolbase/pset.h b/dtool/src/dtoolbase/pset.h index 77bcfa2b67..4b1ca1617c 100644 --- a/dtool/src/dtoolbase/pset.h +++ b/dtool/src/dtoolbase/pset.h @@ -24,7 +24,7 @@ #include #endif -#ifndef USE_STL_ALLOCATOR +#if !defined(USE_STL_ALLOCATOR) || defined(CPPPARSER) // If we're not using custom allocators, just use the standard class // definition. #define pset set diff --git a/dtool/src/dtoolbase/pvector.h b/dtool/src/dtoolbase/pvector.h index 74f51d2d50..14bd542f37 100644 --- a/dtool/src/dtoolbase/pvector.h +++ b/dtool/src/dtoolbase/pvector.h @@ -25,6 +25,12 @@ // definition. #define pvector vector +#elif defined(CPPPARSER) +// Simplified definition to speed up Interrogate parsing. +template +class pvector : public vector { +}; + #else /** diff --git a/dtool/src/interrogate/interfaceMaker.cxx b/dtool/src/interrogate/interfaceMaker.cxx index a653dc4438..f13e16244e 100644 --- a/dtool/src/interrogate/interfaceMaker.cxx +++ b/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) { diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 37932246db..e6bcf05d14 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -4794,6 +4794,26 @@ write_function_instance(ostream &out, FunctionRemap *remap, clear_error = true; 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)) { if (args_type == AT_single_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_wchar_pointer(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, // defined in py_panda.h. indent(out, indent_level) @@ -6713,6 +6734,8 @@ is_cpp_type_legal(CPPType *in_ctype) { return true; } else if (TypeManager::is_basic_string_wchar(type)) { return true; + } else if (TypeManager::is_vector_unsigned_char(type)) { + return true; } else if (TypeManager::is_simple(type)) { return true; } else if (TypeManager::is_pointer_to_simple(type)) { diff --git a/dtool/src/interrogate/typeManager.cxx b/dtool/src/interrogate/typeManager.cxx index 1fe51f8111..7c9b6582a3 100644 --- a/dtool/src/interrogate/typeManager.cxx +++ b/dtool/src/interrogate/typeManager.cxx @@ -937,6 +937,66 @@ is_wstring(CPPType *type) { return is_basic_string_wchar(type); } +/** + * Returns true if the type is vector, 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. + */ +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. */ diff --git a/dtool/src/interrogate/typeManager.h b/dtool/src/interrogate/typeManager.h index 5c5ed18190..4e5356a24e 100644 --- a/dtool/src/interrogate/typeManager.h +++ b/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_ptr_to_basic_string_wchar(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_bool(CPPType *type); static bool is_integer(CPPType *type); diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index eebefb036b..8491c7529f 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -128,6 +128,13 @@ typedef long Py_hash_t; #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; // this is tempory .. untill this is glued better into the panda build system diff --git a/panda/src/express/hashVal.I b/panda/src/express/hashVal.I index d866e56475..6519915034 100644 --- a/panda/src/express/hashVal.I +++ b/panda/src/express/hashVal.I @@ -184,6 +184,16 @@ INLINE void HashVal:: hash_string(const string &data) { 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 &data) { + hash_buffer((const char *)&data[0], data.size()); +} #endif // HAVE_OPENSSL /** diff --git a/panda/src/express/hashVal.h b/panda/src/express/hashVal.h index 1002669e43..d0652d1e01 100644 --- a/panda/src/express/hashVal.h +++ b/panda/src/express/hashVal.h @@ -68,6 +68,7 @@ PUBLISHED: bool hash_stream(istream &stream); INLINE void hash_ramfile(const Ramfile &ramfile); INLINE void hash_string(const string &data); + INLINE void hash_bytes(const pvector &data); void hash_buffer(const char *buffer, int length); #endif // HAVE_OPENSSL