diff options
-rw-r--r-- | generator/cppgenerator.cpp | 127 | ||||
-rw-r--r-- | libshiboken/sbkenum.cpp | 75 | ||||
-rw-r--r-- | libshiboken/sbkenum.h | 35 |
3 files changed, 172 insertions, 65 deletions
diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 7dcb263a4..79b168f89 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3142,8 +3142,7 @@ void CppGenerator::writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList { if (enums.isEmpty()) return; - s << INDENT << "// Initialization of enums." << endl; - s << INDENT << "PyObject* enumItem;" << endl << endl; + s << INDENT << "// Initialization of enums." << endl << endl; foreach (const AbstractMetaEnum* cppEnum, enums) { if (cppEnum->isPrivate()) continue; @@ -3154,54 +3153,44 @@ void CppGenerator::writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* cppEnum) { const AbstractMetaClass* enclosingClass = getProperEnclosingClassForEnum(cppEnum); - QString cpythonName = cpythonEnumName(cppEnum); - QString addFunction; + const AbstractMetaClass* upper = enclosingClass ? enclosingClass->enclosingClass() : 0; + bool hasUpperEnclosingClass = upper && upper->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; + QString enclosingObjectVariable; if (enclosingClass) - addFunction = "PyDict_SetItemString(" + cpythonTypeName(enclosingClass) + ".super.ht_type.tp_dict,"; - else if (cppEnum->isAnonymous()) - addFunction = "PyModule_AddIntConstant(module,"; + enclosingObjectVariable = '&' + cpythonTypeName(enclosingClass); + else if (hasUpperEnclosingClass) + enclosingObjectVariable = "enclosingClass"; else - addFunction = "PyModule_AddObject(module,"; + enclosingObjectVariable = "module"; - s << INDENT << "// init "; - if (cppEnum->isAnonymous()) - s << "anonymous enum identified by enum value: "; - else - s << "enum: "; - s << cppEnum->name() << endl; + s << INDENT << "// Initialization of "; + s << (cppEnum->isAnonymous() ? "anonymous enum identified by enum value" : "enum"); + s << " '" << cppEnum->name() << "'." << endl; if (!cppEnum->isAnonymous()) { - - s << INDENT << "PyTypeObject* " << cpythonName << " = Shiboken::Enum::newTypeWithName(\"" << getClassTargetFullName(cppEnum) << "\", \"" - << (cppEnum->enclosingClass() ? cppEnum->enclosingClass()->qualifiedCppName() + "::" : "") << cppEnum->name() << "\");" << endl; - - if (cppEnum->typeEntry()->flags()) - s << INDENT << cpythonName << "->tp_as_number = &" << cpythonName << "_as_number;" << endl; - - s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = " << cpythonName << ';' << endl; - s << INDENT << "if (PyType_Ready(" << cpythonName << ") < 0)" << endl; - s << INDENT << INDENT << "return;" << endl; - - s << INDENT << addFunction << endl; - s << INDENT << INDENT << INDENT << '\"' << cppEnum->name() << "\","; - s << "((PyObject*)" << cpythonName << "));" << endl << endl; - FlagsTypeEntry* flags = cppEnum->typeEntry()->flags(); - if (flags) { - QString flagsName = cpythonFlagsName(flags); - s << INDENT << "// init flags class: " << flags->name() << endl; + if (flags) s << INDENT << cpythonTypeNameExt(flags) << " = &" << cpythonTypeName(flags) << ';' << endl; - - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << flagsName << "_Type) < 0)" << endl; - s << INDENT << INDENT << "return;" << endl; - - s << INDENT << addFunction << endl; - s << INDENT << INDENT << INDENT << '\"' << flags->flagsName() << "\","; - s << "((PyObject*)&" << flagsName << "_Type));" << endl << endl; + s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = Shiboken::Enum::"; + s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum"); + s << '(' << enclosingObjectVariable << ',' << endl; + { + Indentation indent(INDENT); + s << INDENT << '"' << cppEnum->name() << "\"," << endl; + s << INDENT << '"' << getClassTargetFullName(cppEnum) << "\"," << endl; + s << INDENT << '"' << (cppEnum->enclosingClass() ? cppEnum->enclosingClass()->qualifiedCppName() + "::" : ""); + s << cppEnum->name() << '"'; + if (flags) + s << ',' << endl << INDENT << cpythonTypeNameExt(flags); + s << ");" << endl; + } + s << INDENT << "if (!" << cpythonTypeNameExt(cppEnum->typeEntry()) << ')' << endl; + { + Indentation indent(INDENT); + s << INDENT << "return;" << endl << endl; } } - foreach (const AbstractMetaEnumValue* enumValue, cppEnum->values()) { if (cppEnum->typeEntry()->isEnumValueRejected(enumValue->name())) continue; @@ -3216,37 +3205,45 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu enumValueText += QString::number(enumValue->value()); } - bool shouldDecrefNumber = false; - QString enumItemText = "enumItem"; - if (!cppEnum->isAnonymous()) { - s << INDENT << "enumItem = Shiboken::Enum::newItem(" << cpythonName << "," << enumValueText; - s << ", \"" << enumValue->name() << "\");" << endl; - } else if (enclosingClass) { - s << INDENT << "enumItem = PyInt_FromLong(" << enumValueText << ");" << endl; - shouldDecrefNumber = true; + if (cppEnum->isAnonymous()) { + if (enclosingClass || hasUpperEnclosingClass) { + s << INDENT << '{' << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyObject* anonEnumItem = PyInt_FromLong(" << enumValueText << ");" << endl; + s << INDENT << "if (PyDict_SetItemString(((SbkObjectType*)" << enclosingObjectVariable; + s << ")->super.ht_type.tp_dict, \"" << enumValue->name() << "\", anonEnumItem) < 0)" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return;" << endl; + } + s << INDENT << "Py_DECREF(anonEnumItem);" << endl; + } + s << INDENT << '}' << endl; + } else { + s << INDENT << "if (PyModule_AddIntConstant(module, \"" << enumValue->name() << "\", "; + s << enumValueText << ") < 0)" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return;" << endl; + } + } } else { - enumItemText = enumValueText; - } - - s << INDENT << addFunction << '"' << enumValue->name() << "\", " << enumItemText << ");" << endl; - if (shouldDecrefNumber) - s << INDENT << "Py_DECREF(enumItem);" << endl; - - if (!cppEnum->isAnonymous()) { - s << INDENT << "Py_DECREF(enumItem);" << endl; - s << INDENT << "PyDict_SetItemString(" << cpythonName << "->tp_dict,"; - s << '"' << enumValue->name() << "\", enumItem);" << endl; - s << INDENT << "Py_DECREF(enumItem);" << endl; + s << INDENT << "if (!Shiboken::Enum::"; + s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem"); + s << '(' << cpythonTypeNameExt(cppEnum->typeEntry()) << ',' << endl; + Indentation indent(INDENT); + s << INDENT << enclosingObjectVariable << ", \"" << enumValue->name() << "\", "; + s << enumValueText << "))" << endl; + s << INDENT << "return;" << endl; } } - if (!cppEnum->isAnonymous()) { - // TypeResolver stuff + // TypeResolver stuff + if (!cppEnum->isAnonymous()) writeRegisterType(s, cppEnum); - } - - s << INDENT << "// end of enum " << cppEnum->name() << endl << endl; + s << INDENT << "// End of '" << cppEnum->name() << "' enum." << endl << endl; } void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass) diff --git a/libshiboken/sbkenum.cpp b/libshiboken/sbkenum.cpp index e128a059a..e05f5cdad 100644 --- a/libshiboken/sbkenum.cpp +++ b/libshiboken/sbkenum.cpp @@ -21,6 +21,7 @@ */ #include "sbkenum.h" +#include "basewrapper.h" #include <string.h> #include <cstring> #include <list> @@ -175,6 +176,80 @@ PyObject* getEnumItemFromValue(PyTypeObject* enumType, long itemValue) return 0; } +static PyTypeObject* createEnum(const char* fullName, const char* cppName, PyTypeObject* flagsType) +{ + PyTypeObject* enumType = newTypeWithName(fullName, cppName); + if (flagsType) { + if (PyType_Ready(flagsType) < 0) + return 0; + enumType->tp_as_number = flagsType->tp_as_number; + } + if (PyType_Ready(enumType) < 0) + return 0; + return enumType; +} + +PyTypeObject* createGlobalEnum(PyObject* module, const char* name, const char* fullName, const char* cppName, PyTypeObject* flagsType) +{ + PyTypeObject* enumType = createEnum(fullName, cppName, flagsType); + if (enumType) { + if (PyModule_AddObject(module, name, (PyObject*)enumType) < 0) + return 0; + } + if (flagsType) { + if (PyModule_AddObject(module, flagsType->tp_name, (PyObject*)flagsType) < 0) + return 0; + } + return enumType; +} + +PyTypeObject* createScopedEnum(SbkObjectType* scope, const char* name, const char* fullName, const char* cppName, PyTypeObject* flagsType) +{ + PyTypeObject* enumType = createEnum(fullName, cppName, flagsType); + if (enumType) { + if (PyDict_SetItemString(scope->super.ht_type.tp_dict, name, (PyObject*)enumType) < 0) + return 0; + } + if (flagsType) { + if (PyDict_SetItemString(scope->super.ht_type.tp_dict, flagsType->tp_name, (PyObject*)flagsType) < 0) + return 0; + } + return enumType; +} + +static PyObject* createEnumItem(PyTypeObject* enumType, const char* itemName, long itemValue) +{ + PyObject* enumItem = newItem(enumType, itemValue, itemName); + if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0) + return 0; + Py_DECREF(enumItem); + return enumItem; +} + +bool createGlobalEnumItem(PyTypeObject* enumType, PyObject* module, const char* itemName, long itemValue) +{ + PyObject* enumItem = createEnumItem(enumType, itemName, itemValue); + if (enumItem) { + if (PyModule_AddObject(module, itemName, enumItem) < 0) + return false; + Py_DECREF(enumItem); + return true; + } + return false; +} + +bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue) +{ + PyObject* enumItem = createEnumItem(enumType, itemName, itemValue); + if (enumItem) { + if (PyDict_SetItemString(scope->super.ht_type.tp_dict, itemName, enumItem) < 0) + return false; + Py_DECREF(enumItem); + return true; + } + return false; +} + PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName) { bool newValue = true; diff --git a/libshiboken/sbkenum.h b/libshiboken/sbkenum.h index c61afed91..52a0b6ffc 100644 --- a/libshiboken/sbkenum.h +++ b/libshiboken/sbkenum.h @@ -30,6 +30,7 @@ extern "C" { extern LIBSHIBOKEN_API PyTypeObject SbkEnumType_Type; +struct SbkObjectType; } // extern "C" @@ -43,6 +44,40 @@ inline bool isShibokenEnum(PyObject* pyObj) namespace Enum { + /** + * Creates a new enum type (and its flags type, if any is given) + * and registers it to Python and adds it to \p module. + * \param module Module to where the new enum type will be added. + * \param name Name of the enum. + * \param fullName Name of the enum that includes all scope information (e.g.: "module.Enum"). + * \param cppName Full qualified C++ name of the enum. + * \param flagsType Optional Python type for the flags associated with the enum. + * \return The new enum type or NULL if it fails. + */ + LIBSHIBOKEN_API PyTypeObject* createGlobalEnum(PyObject* module, + const char* name, + const char* fullName, + const char* cppName, + PyTypeObject* flagsType = 0); + /// This function does the same as createGlobalEnum, but adds the enum to a Shiboken type or namespace. + LIBSHIBOKEN_API PyTypeObject* createScopedEnum(SbkObjectType* scope, + const char* name, + const char* fullName, + const char* cppName, + PyTypeObject* flagsType = 0); + + /** + * Creates a new enum item for a given enum type and adds it to \p module. + * \param enumType Enum type to where the new enum item will be added. + * \param module Module to where the enum type of the new enum item belongs. + * \param itemName Name of the enum item. + * \param itemValue Numerical value of the enum item. + * \return true if everything goes fine, false if it fails. + */ + LIBSHIBOKEN_API bool createGlobalEnumItem(PyTypeObject* enumType, PyObject* module, const char* itemName, long itemValue); + /// This function does the same as createGlobalEnumItem, but adds the enum to a Shiboken type or namespace. + LIBSHIBOKEN_API bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue); + LIBSHIBOKEN_API PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName = 0); LIBSHIBOKEN_API PyTypeObject* newType(const char* name); //Deprecated use 'newTypeWithName' |