Alien-SmokeQt
view release on metacpan or search on metacpan
generator/generators/smoke/writeClasses.cpp view on Meta::CPAN
/*
Generator for the SMOKE sources
Copyright (C) 2009 Arno Rehn <arno@arnorehn.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QMap>
#include <QSet>
#include <QTextStream>
#include <type.h>
#include "globals.h"
#include "../../options.h"
SmokeClassFiles::SmokeClassFiles(SmokeDataFile *data)
: m_smokeData(data)
{
}
void SmokeClassFiles::write()
{
write(m_smokeData->includedClasses);
}
void SmokeClassFiles::write(const QList<QString>& keys)
{
qDebug("writing out x_*.cpp [%s]", qPrintable(Options::module));
// how many classes go in one file
int count = keys.count() / Options::parts;
int count2 = count;
for (int i = 0; i < Options::parts; i++) {
QSet<QString> includes;
QString classCode;
QTextStream classOut(&classCode);
// write the class code to a QString so we can later prepend the #includes
if (i == Options::parts - 1) count2 = -1;
foreach (const QString& str, keys.mid(count * i, count2)) {
const Class* klass = &classes[str];
includes.insert(klass->fileName());
writeClass(classOut, klass, str, includes);
}
// create the file
QFile file(Options::outputDir.filePath("x_" + QString::number(i + 1) + ".cpp"));
file.open(QFile::ReadWrite | QFile::Truncate);
QTextStream fileOut(&file);
// write out the header
fileOut << "//Auto-generated by " << QCoreApplication::arguments()[0] << ". DO NOT EDIT.\n";
// ... and the #includes
QList<QString> sortedIncludes = includes.toList();
qSort(sortedIncludes.begin(), sortedIncludes.end());
foreach (const QString& str, sortedIncludes) {
if (str.isEmpty())
continue;
fileOut << "#include <" << str << ">\n";
}
fileOut << "\n#include <smoke.h>\n#include <" << Options::module << "_smoke.h>\n";
fileOut << "\nclass __internal_SmokeClass {};\n";
fileOut << "\nnamespace __smoke" << Options::module << " {\n\n";
// now the class code
fileOut << classCode;
fileOut << "\n}\n";
file.close();
}
}
QString SmokeClassFiles::generateMethodBody(const QString& indent, const QString& className, const QString& smokeClassName, const Method& meth,
int index, bool dynamicDispatch, QSet<QString>& includes)
{
QString methodBody;
QTextStream out(&methodBody);
out << indent;
if (meth.isConstructor()) {
out << smokeClassName << "* xret = new " << smokeClassName << "(";
} else {
const Function* func = Util::globalFunctionMap[&meth];
if (func)
includes.insert(func->fileName());
if (meth.type()->getClass())
includes.insert(meth.type()->getClass()->fileName());
if (meth.type()->isFunctionPointer() || meth.type()->isArray())
out << meth.type()->toString("xret") << " = ";
else if (meth.type() != Type::Void)
out << meth.type()->toString() << " xret = ";
if (!(meth.flags() & Method::Static)) {
if (meth.isConst()) {
out << "((const " << smokeClassName << "*)this)->";
} else {
out << "this->";
}
}
if (!dynamicDispatch && !func) {
// dynamic dispatch not wanted, call with 'this->Foo::method()'
out << className << "::";
} else if (func) {
if (!func->nameSpace().isEmpty())
out << func->nameSpace() << "::";
}
out << meth.name() << "(";
}
for (int j = 0; j < meth.parameters().count(); j++) {
const Parameter& param = meth.parameters()[j];
if (param.type()->getClass())
includes.insert(param.type()->getClass()->fileName());
if (j > 0) out << ",";
QString field = Util::stackItemField(param.type());
QString typeName = param.type()->toString();
if (param.type()->isArray()) {
Type t = *param.type();
t.setPointerDepth(t.pointerDepth() + 1);
t.setIsRef(false);
typeName = t.toString();
out << '*';
} else if (field == "s_class" && (param.type()->pointerDepth() == 0 || param.type()->isRef()) && !param.type()->isFunctionPointer()) {
// references and classes are passed in s_class
typeName.append('*');
out << '*';
}
// casting to a reference doesn't make sense in this case
if (param.type()->isRef() && !param.type()->isFunctionPointer()) typeName.replace('&', "");
out << "(" << typeName << ")" << "x[" << j + 1 << "]." << field;
}
// if the method has any other default parameters, append them here as values
if (!meth.remainingDefaultValues().isEmpty()) {
const QStringList& defaultParams = meth.remainingDefaultValues();
if (meth.parameters().count() > 0)
out << "," ;
out << defaultParams.join(",");
( run in 0.717 second using v1.01-cache-2.11-cpan-13bb782fe5a )