aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-07-21 21:48:21 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:17:06 -0300
commit5afdf1fae25fdb7f8e090c24d6526dccbba18e21 (patch)
tree072235eddb5dda7ad2242e59eb7e043cfd5a6440
parent808c7b33fe6aafc81c58ec4850c0e30dcfbd91e9 (diff)
Added functions to provide a cleaner enum and flags initialization.
The functions are: Shiboken::Enum::createGlobalEnum() Shiboken::Enum::createScopedEnum() Shiboken::Enum::createGlobalEnumItem() Shiboken::Enum::createScopedEnumItem() Also updated the generator to make use of them.
-rw-r--r--generator/cppgenerator.cpp127
-rw-r--r--libshiboken/sbkenum.cpp75
-rw-r--r--libshiboken/sbkenum.h35
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'