Skip to content

Commit

Permalink
New conversions for containers.
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcelo Lira committed Dec 9, 2011
1 parent cda2c51 commit 11a09fe
Show file tree
Hide file tree
Showing 20 changed files with 1,076 additions and 143 deletions.
282 changes: 206 additions & 76 deletions generator/cppgenerator.cpp

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions generator/cppgenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class CppGenerator : public ShibokenGenerator
void writeCustomConverterFunctions(QTextStream& s, const CustomConversion* customConversion);
void writeConverterRegister(QTextStream& s, const AbstractMetaClass* metaClass);
void writeCustomConverterRegister(QTextStream& s, const CustomConversion* customConversion, const QString& converterVar);
void writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar);

void writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType);

void writeMethodWrapperPreamble(QTextStream& s, OverloadData& overloadData);
void writeConstructorWrapper(QTextStream& s, const AbstractMetaFunctionList overloads);
Expand Down Expand Up @@ -164,6 +167,7 @@ class CppGenerator : public ShibokenGenerator
/// Writes a C++ to Python conversion function.
void writeCppToPythonFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, QString targetTypeName = QString());
void writeCppToPythonFunction(QTextStream& s, const CustomConversion* customConversion);
void writeCppToPythonFunction(QTextStream& s, const AbstractMetaType* containerType);

/// Writes a Python to C++ conversion function.
void writePythonToCppFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, const QString& targetTypeName);
Expand All @@ -188,6 +192,9 @@ class CppGenerator : public ShibokenGenerator
const CustomConversion::TargetToNativeConversion* toNative,
const TypeEntry* targetType);

/// Writes a pair of Python to C++ conversion and check functions for instantiated container types.
void writePythonToCppConversionFunctions(QTextStream& s, const AbstractMetaType* containerType);

void writeAddPythonToCppConversion(QTextStream& s, const QString& converterVar, const QString& pythonToCppFunc, const QString& isConvertibleFunc);

void writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs);
Expand Down Expand Up @@ -242,6 +249,7 @@ class CppGenerator : public ShibokenGenerator
void writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass);

void writePrimitiveConverterInitialization(QTextStream& s, const CustomConversion* customConversion);
void writeContainerConverterInitialization(QTextStream& s, const AbstractMetaType* type);
void writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList<const AbstractMetaClass*>& conversions);

void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn);
Expand Down
14 changes: 14 additions & 0 deletions generator/headergenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,20 @@ void HeaderGenerator::finishGeneration()
_writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(ptype), pCount);
pCount++;
}

foreach (const AbstractMetaType* container, instantiatedContainers()) {
//_writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(container), pCount);
// DEBUG
QString variableName = getTypeIndexVariableName(container);
macrosStream << "#define ";
macrosStream.setFieldWidth(60);
macrosStream << variableName;
macrosStream.setFieldWidth(0);
macrosStream << ' ' << pCount << " // " << container->cppSignature() << endl;
// DEBUG
pCount++;
}

// Because on win32 the compiler will not accept a zero length array.
if (pCount == 0)
pCount++;
Expand Down
164 changes: 122 additions & 42 deletions generator/shibokengenerator.cpp

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion generator/shibokengenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
"This will result in a compilation error."
#define PYTHON_TO_CPP_VAR "pythonToCpp"

#define CHECKTYPE_REGEX "%CHECKTYPE\\[([^\\[]*)\\]\\("
#define ISCONVERTIBLE_REGEX "%ISCONVERTIBLE\\[([^\\[]*)\\]\\("
#define CONVERTTOPYTHON_REGEX "%CONVERTTOPYTHON\\[([^\\[]*)\\]\\("
#define CONVERTTOCPP_REGEX "(\\*?%?[a-zA-Z_][\\w\\.]*(?:\\[[^\\[^<^>]+\\])*)"\
"(?:\\s+)=(?:\\s+)%CONVERTTOCPP\\[([^\\[]*)\\]\\("

#include <generator.h>
#include <QtCore/QTextStream>

Expand Down Expand Up @@ -507,7 +513,7 @@ class ShibokenGenerator : public Generator
ExtendedConverterData getExtendedConverters() const;

/// Returns a list of converters for the non wrapper types of the current module.
QList<const CustomConversion*> getNonWrapperCustomConversions();
QList<const CustomConversion*> getPrimitiveCustomConversions();

/// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments.
static bool pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData);
Expand Down
122 changes: 122 additions & 0 deletions libshiboken/sbkconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "sbkconverter_p.h"
#include "basewrapper_p.h"
#include "google/dense_hash_map"
#include "autodecref.h"
#include "sbkdbg.h"

static SbkConverter** PrimitiveTypeConverters;
Expand Down Expand Up @@ -299,4 +300,125 @@ SbkConverter* primitiveTypeConverter(int index)
return PrimitiveTypeConverters[index];
}

bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn)
{
assert(type);
assert(pyIn);
if (!PySequence_Check(pyIn))
return false;
int size = PySequence_Size(pyIn);
for (int i = 0; i < size; ++i) {
if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, i)), type))
return false;
}
return true;
}
bool convertibleSequenceTypes(SbkConverter* converter, PyObject* pyIn)
{
assert(converter);
assert(pyIn);
if (!PySequence_Check(pyIn))
return false;
int size = PySequence_Size(pyIn);
for (int i = 0; i < size; ++i) {
if (!isPythonToCppConvertible(converter, AutoDecRef(PySequence_GetItem(pyIn, i))))
return false;
}
return true;
}
bool convertibleSequenceTypes(SbkObjectType* type, PyObject* pyIn)
{
assert(type);
return convertibleSequenceTypes(type->d->converter, pyIn);
}

bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn)
{
assert(firstType);
assert(secondType);
assert(pyIn);
if (!PySequence_Check(pyIn))
return false;
if (PySequence_Size(pyIn) != 2)
return false;
if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 0)), firstType))
return false;
if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 1)), secondType))
return false;
return true;
}
bool convertiblePairTypes(SbkConverter* firstConverter, bool firstCheckExact, SbkConverter* secondConverter, bool secondCheckExact, PyObject* pyIn)
{
assert(firstConverter);
assert(secondConverter);
assert(pyIn);
if (!PySequence_Check(pyIn))
return false;
if (PySequence_Size(pyIn) != 2)
return false;
AutoDecRef firstItem(PySequence_GetItem(pyIn, 0));
if (firstCheckExact) {
if (!PyObject_TypeCheck(firstItem, firstConverter->pythonType))
return false;
} else if (!isPythonToCppConvertible(firstConverter, firstItem)) {
return false;
}
AutoDecRef secondItem(PySequence_GetItem(pyIn, 1));
if (secondCheckExact) {
if (!PyObject_TypeCheck(secondItem, secondConverter->pythonType))
return false;
} else if (!isPythonToCppConvertible(secondConverter, secondItem)) {
return false;
}

return true;
}

bool checkDictTypes(PyTypeObject* keyType, PyTypeObject* valueType, PyObject* pyIn)
{
assert(keyType);
assert(valueType);
assert(pyIn);
if (!PyDict_Check(pyIn))
return false;

PyObject* key;
PyObject* value;
Py_ssize_t pos = 0;
while (PyDict_Next(pyIn, &pos, &key, &value)) {
if (!PyObject_TypeCheck(key, keyType))
return false;
if (!PyObject_TypeCheck(value, valueType))
return false;
}
return true;
}

bool convertibleDictTypes(SbkConverter* keyConverter, bool keyCheckExact, SbkConverter* valueConverter, bool valueCheckExact, PyObject* pyIn)
{
assert(keyConverter);
assert(valueConverter);
assert(pyIn);
if (!PyDict_Check(pyIn))
return false;
PyObject* key;
PyObject* value;
Py_ssize_t pos = 0;
while (PyDict_Next(pyIn, &pos, &key, &value)) {
if (keyCheckExact) {
if (!PyObject_TypeCheck(key, keyConverter->pythonType))
return false;
} else if (!isPythonToCppConvertible(keyConverter, key)) {
return false;
}
if (valueCheckExact) {
if (!PyObject_TypeCheck(value, valueConverter->pythonType))
return false;
} else if (!isPythonToCppConvertible(valueConverter, value)) {
return false;
}
}
return true;
}

} } // namespace Shiboken::Conversions
22 changes: 22 additions & 0 deletions libshiboken/sbkconverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,28 @@ LIBSHIBOKEN_API SbkConverter* getConverter(const char* typeName);
/// Returns the converter for a primitive type.
LIBSHIBOKEN_API SbkConverter* primitiveTypeConverter(int index);

/// Returns true if a Python sequence is comprised of objects of the given \p type.
LIBSHIBOKEN_API bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn);

/// Returns true if a Python sequence is comprised of objects of a type convertible to the one represented by the given \p converter.
LIBSHIBOKEN_API bool convertibleSequenceTypes(SbkConverter* converter, PyObject* pyIn);

/// Returns true if a Python sequence is comprised of objects of a type convertible to \p type.
LIBSHIBOKEN_API bool convertibleSequenceTypes(SbkObjectType* type, PyObject* pyIn);

/// Returns true if a Python sequence can be converted to a C++ pair.
LIBSHIBOKEN_API bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn);

/// Returns true if a Python sequence can be converted to a C++ pair.
LIBSHIBOKEN_API bool convertiblePairTypes(SbkConverter* firstConverter, bool firstCheckExact, SbkConverter* secondConverter, bool secondCheckExact, PyObject* pyIn);

/// Returns true if a Python dictionary can be converted to a C++ hash or map.
LIBSHIBOKEN_API bool checkDictTypes(PyTypeObject* keyType, PyTypeObject* valueType, PyObject* pyIn);

/// Returns true if a Python dictionary can be converted to a C++ hash or map.
LIBSHIBOKEN_API bool convertibleDictTypes(SbkConverter* keyConverter, bool keyCheckExact, SbkConverter* valueConverter, bool valueCheckExact, PyObject* pyIn);


#define SBK_PY_LONG_LONG_IDX 0
#define SBK_BOOL_IDX 1
#define SBK_CHAR_IDX 2
Expand Down
Loading

0 comments on commit 11a09fe

Please sign in to comment.