Alien-SmokeQt
view release on metacpan or search on metacpan
generator/generators/smoke/helpers.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 <QHash>
#include <QList>
#include <QStack>
#include <type.h>
#include "globals.h"
#include "../../options.h"
QHash<QString, QString> Util::typeMap;
QHash<const Method*, const Function*> Util::globalFunctionMap;
QHash<const Method*, const Field*> Util::fieldAccessors;
// looks up the inheritance path from desc to super and sets 'virt' to true if it encounters a virtual base
static bool isVirtualInheritancePathPrivate(const Class* desc, const Class* super, bool *virt)
{
foreach (const Class::BaseClassSpecifier bspec, desc->baseClasses()) {
if (bspec.baseClass == super || isVirtualInheritancePathPrivate(bspec.baseClass, super, virt)) {
if (bspec.isVirtual)
*virt = true;
return true;
}
}
return false;
}
bool Util::isVirtualInheritancePath(const Class* desc, const Class* super)
{
bool isVirtual = false;
isVirtualInheritancePathPrivate(desc, super, &isVirtual);
return isVirtual;
}
QList<const Class*> Util::superClassList(const Class* klass)
{
static QHash<const Class*, QList<const Class*> > superClassCache;
QList<const Class*> ret;
if (superClassCache.contains(klass))
return superClassCache[klass];
foreach (const Class::BaseClassSpecifier& base, klass->baseClasses()) {
ret << base.baseClass;
ret += superClassList(base.baseClass);
}
// cache
superClassCache[klass] = ret;
return ret;
}
QList<const Class*> Util::descendantsList(const Class* klass)
{
static QHash<const Class*, QList<const Class*> > descendantsClassCache;
QList<const Class*> ret;
if (descendantsClassCache.contains(klass))
return descendantsClassCache[klass];
for (QHash<QString, Class>::const_iterator iter = classes.constBegin(); iter != classes.constEnd(); iter++) {
if (superClassList(&iter.value()).contains(klass))
ret << &iter.value();
}
// cache
descendantsClassCache[klass] = ret;
return ret;
}
bool operator==(const Field& lhs, const Field& rhs)
{
return (lhs.name() == rhs.name() && lhs.declaringType() == rhs.declaringType() && lhs.type() == rhs.type());
}
bool operator==(const EnumMember& lhs, const EnumMember& rhs)
{
return (lhs.name() == rhs.name() && lhs.declaringType() == rhs.declaringType() && lhs.type() == rhs.type());
}
void Util::preparse(QSet<Type*> *usedTypes, QSet<const Class*> *superClasses, const QList<QString>& keys)
{
Class& globalSpace = classes["QGlobalSpace"];
globalSpace.setName("QGlobalSpace");
globalSpace.setKind(Class::Kind_Class);
globalSpace.setIsNameSpace(true);
// add all functions as methods to a class called 'QGlobalSpace' or a class that represents a namespace
for (QHash<QString, Function>::const_iterator it = functions.constBegin(); it != functions.constEnd(); it++) {
const Function& fn = it.value();
QString fnString = fn.toString();
// gcc doesn't like this function... for whatever reason
if (fn.name() == "_IO_ftrylockfile"
// functions in named namespaces are covered by the class list - only check for top-level functions here
|| (fn.nameSpace().isEmpty() && !Options::functionNameIncluded(fn.qualifiedName()) && !Options::functionSignatureIncluded(fnString))
|| Options::typeExcluded(fnString))
{
// we don't want that function...
continue;
}
Class* parent = &globalSpace;
if (!fn.nameSpace().isEmpty()) {
parent = &classes[fn.nameSpace()];
if (parent->name().isEmpty()) {
parent->setName(fn.nameSpace());
parent->setKind(Class::Kind_Class);
parent->setIsNameSpace(true);
}
}
Method meth = Method(parent, fn.name(), fn.type(), Access_public, fn.parameters());
meth.setFlag(Method::Static);
parent->appendMethod(meth);
// map this method to the function, so we can later retrieve the header it was defined in
globalFunctionMap[&parent->methods().last()] = &fn;
int methIndex = parent->methods().size() - 1;
addOverloads(meth);
// handle the methods appended by addOverloads()
for (int i = parent->methods().size() - 1; i > methIndex; --i)
globalFunctionMap[&parent->methods()[i]] = &fn;
(*usedTypes) << meth.type();
foreach (const Parameter& param, meth.parameters())
(*usedTypes) << param.type();
}
// all enums that don't have a parent are put under QGlobalSpace, too
for (QHash<QString, Enum>::iterator it = enums.begin(); it != enums.end(); it++) {
Enum& e = it.value();
if (!e.parent()) {
Class* parent = &globalSpace;
if (!e.nameSpace().isEmpty()) {
parent = &classes[e.nameSpace()];
if (parent->name().isEmpty()) {
parent->setName(e.nameSpace());
parent->setKind(Class::Kind_Class);
parent->setIsNameSpace(true);
}
}
Type *t = 0;
if (e.name().isEmpty()) {
// unnamed enum
Type longType = Type("long");
longType.setIsIntegral(true);
t = Type::registerType(longType);
} else {
t = Type::registerType(Type(&e));
}
(*usedTypes) << t;
parent->appendChild(&e);
}
}
foreach (const QString& key, keys) {
Class& klass = classes[key];
foreach (const Class::BaseClassSpecifier base, klass.baseClasses()) {
superClasses->insert(base.baseClass);
}
if (!klass.isNameSpace()) {
addDefaultConstructor(&klass);
addCopyConstructor(&klass);
addDestructor(&klass);
checkForAbstractClass(&klass);
foreach (const Method& m, klass.methods()) {
if (m.access() == Access_private)
continue;
if ((m.type()->getClass() && m.type()->getClass()->access() == Access_private)
|| Options::typeExcluded(m.toString(false, true)))
{
klass.methodsRef().removeOne(m);
continue;
}
addOverloads(m);
(*usedTypes) << m.type();
foreach (const Parameter& param, m.parameters())
(*usedTypes) << param.type();
}
foreach (const Field& f, klass.fields()) {
if (f.access() == Access_private)
continue;
if (Options::typeExcluded(f.toString(false, true))) {
klass.fieldsRef().removeOne(f);
continue;
}
}
foreach (const Field& f, klass.fields()) {
if (f.access() == Access_private)
continue;
addAccessorMethods(f, usedTypes);
}
( run in 0.511 second using v1.01-cache-2.11-cpan-13bb782fe5a )