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

This commit is contained in:
rdb 2016-06-03 01:47:54 +02:00
parent 242cc5f57d
commit 5543716660
14 changed files with 127 additions and 7 deletions

View File

@ -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

View File

@ -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.

View File

@ -19,7 +19,7 @@
#include "register_type.h"
#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
// definition.
#define pdeque deque

View File

@ -19,7 +19,7 @@
#include "register_type.h"
#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
// definition.
#define plist list

View File

@ -24,7 +24,7 @@
#include <hash_map>
#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

View File

@ -24,7 +24,7 @@
#include <hash_set>
#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

View File

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

View File

@ -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) {

View File

@ -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)) {

View File

@ -937,6 +937,66 @@ is_wstring(CPPType *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.
*/

View File

@ -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);

View File

@ -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

View File

@ -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<unsigned char> &data) {
hash_buffer((const char *)&data[0], data.size());
}
#endif // HAVE_OPENSSL
/**

View File

@ -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<unsigned char> &data);
void hash_buffer(const char *buffer, int length);
#endif // HAVE_OPENSSL