<commit_before>#include "MALLOC.H"

#include <assert.h>
#include "EMULATOR_GLOBALS.H"

void InitHeap(unsigned long* unk00, unsigned long unk01)
{
	UNIMPLEMENTED();
}

void free(void* unk00)
{
	UNIMPLEMENTED();
}

void* malloc(size_t unk00)
{
	UNIMPLEMENTED();
	return NULL;
}

void* calloc(size_t unk00, size_t unk01)
{
	UNIMPLEMENTED();
	return NULL;
}

void* realloc(void * unk00, size_t unk01)
{
	UNIMPLEMENTED();
	return NULL;
}

void InitHeap2(unsigned long* unk00, unsigned long unk01)
{
	UNIMPLEMENTED();
}

void free2(void* unk00)
{
	UNIMPLEMENTED();
}

void* malloc2(size_t unk00)
{
	UNIMPLEMENTED();
	return NULL;
}

void* calloc2(size_t unk00, size_t unk01)
{
	UNIMPLEMENTED();
	return NULL;
}

void* realloc2(void* unk00, size_t unk01)
{
	UNIMPLEMENTED();
	return NULL;
}

void InitHeap3(unsigned long* unk00, unsigned long unk01)
{
	UNIMPLEMENTED();
}

void free3(void* unk00)
{
	UNIMPLEMENTED();
}

void* malloc3(size_t unk00)
{
	UNIMPLEMENTED();
	return NULL;
}

void* calloc3(size_t unk00, size_t unk01)
{
	UNIMPLEMENTED();
	return NULL;
}

void* realloc3(void* unk00, size_t unk01)
{
	UNIMPLEMENTED();
	return NULL;
}
<commit_msg>Attempt to fix travis 1.<commit_after>#include "MALLOC.H"

#include <assert.h>

void InitHeap(unsigned long* unk00, unsigned long unk01)
{

}

void free(void* unk00)
{

}

void* malloc(size_t unk00)
{
	return NULL;
}

void* calloc(size_t unk00, size_t unk01)
{
	return NULL;
}

void* realloc(void * unk00, size_t unk01)
{
	return NULL;
}

void InitHeap2(unsigned long* unk00, unsigned long unk01)
{
}

void free2(void* unk00)
{
}

void* malloc2(size_t unk00)
{
	return NULL;
}

void* calloc2(size_t unk00, size_t unk01)
{
	return NULL;
}

void* realloc2(void* unk00, size_t unk01)
{
	return NULL;
}

void InitHeap3(unsigned long* unk00, unsigned long unk01)
{
}

void free3(void* unk00)
{
}

void* malloc3(size_t unk00)
{
	return NULL;
}

void* calloc3(size_t unk00, size_t unk01)
{
	return NULL;
}

void* realloc3(void* unk00, size_t unk01)
{
	return NULL;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "inputartifactscanner.h"

#include "artifact.h"
#include "buildgraph.h"
#include "productbuilddata.h"
#include "projectbuilddata.h"
#include "transformer.h"
#include "depscanner.h"
#include "rulesevaluationcontext.h"

#include <language/language.h>
#include <tools/fileinfo.h>
#include <tools/scannerpluginmanager.h>
#include <tools/qbsassert.h>
#include <tools/error.h>

#include <QDir>
#include <QSet>
#include <QStringList>
#include <QVariantMap>

namespace qbs {
namespace Internal {

InputArtifactScannerContext::InputArtifactScannerContext(ScanResultCache *scanResultCache)
    : scanResultCache(scanResultCache)
{
}

InputArtifactScannerContext::~InputArtifactScannerContext()
{
}

static void resolveWithIncludePath(const QString &includePath,
        const ScanResultCache::Dependency &dependency, const ResolvedProduct *product,
        ResolvedDependency *result)
{
    QString absDirPath = dependency.dirPath().isEmpty() ? includePath : FileInfo::resolvePath(includePath, dependency.dirPath());
    if (!dependency.isClean())
        absDirPath = QDir::cleanPath(absDirPath);

    ResolvedProject *project = product->project.data();
    FileDependency *fileDependencyArtifact = 0;
    Artifact *dependencyInProduct = 0;
    Artifact *dependencyInOtherProduct = 0;
    foreach (FileResourceBase *lookupResult, project->topLevelProject()
             ->buildData->lookupFiles(absDirPath, dependency.fileName())) {
        if ((fileDependencyArtifact = dynamic_cast<FileDependency *>(lookupResult)))
            continue;
        Artifact * const foundArtifact = dynamic_cast<Artifact *>(lookupResult);
        if (foundArtifact->product == product)
            dependencyInProduct = foundArtifact;
        else
            dependencyInOtherProduct = foundArtifact;
    }

    // prioritize found artifacts
    if ((result->file = dependencyInProduct)
        || (result->file = dependencyInOtherProduct)
        || (result->file = fileDependencyArtifact))
    {
        result->filePath = result->file->filePath();
        return;
    }

    QString absFilePath = absDirPath + QLatin1Char('/') + dependency.fileName();

    // TODO: We probably need a flag that tells us whether directories are allowed.
    const FileInfo fi(absFilePath);
    if (fi.exists(absFilePath) && !fi.isDir())
        result->filePath = absFilePath;
}

static void resolveAbsolutePath(const ScanResultCache::Dependency &dependency,
        const ResolvedProduct *product, ResolvedDependency *result)
{
    QString absDirPath = dependency.dirPath();
    if (!dependency.isClean())
        absDirPath = QDir::cleanPath(absDirPath);

    ResolvedProject *project = product->project.data();
    FileDependency *fileDependencyArtifact = 0;
    Artifact *dependencyInProduct = 0;
    Artifact *dependencyInOtherProduct = 0;
    foreach (FileResourceBase *lookupResult, project->topLevelProject()
             ->buildData->lookupFiles(absDirPath, dependency.fileName())) {
        if ((fileDependencyArtifact = dynamic_cast<FileDependency *>(lookupResult)))
            continue;
        Artifact * const foundArtifact = dynamic_cast<Artifact *>(lookupResult);
        if (foundArtifact->product == product)
            dependencyInProduct = foundArtifact;
        else
            dependencyInOtherProduct = foundArtifact;
    }

    // prioritize found artifacts
    if ((result->file = dependencyInProduct)
        || (result->file = dependencyInOtherProduct)
        || (result->file = fileDependencyArtifact)) {
        result->filePath = result->file->filePath();
        return;
    }

    if (FileInfo::exists(dependency.filePath()))
        result->filePath = dependency.filePath();
}

static void scanWithScannerPlugin(DependencyScanner *scanner,
                                  FileResourceBase *fileToBeScanned,
                                  ScanResultCache::Result *scanResult)
{
    QStringList dependencies = scanner->collectDependencies(fileToBeScanned);
    foreach (const QString &s, dependencies)
        scanResult->deps += ScanResultCache::Dependency(s);
    scanResult->valid = true;
}

InputArtifactScanner::InputArtifactScanner(Artifact *artifact, InputArtifactScannerContext *ctx,
                                           const Logger &logger)
    : m_artifact(artifact), m_context(ctx), m_newDependencyAdded(false), m_logger(logger)
{
}

void InputArtifactScanner::scan()
{
    if (m_artifact->inputsScanned)
        return;

    if (m_logger.traceEnabled()) {
        m_logger.qbsTrace()
                << QString::fromLatin1("[DEPSCAN] inputs for %1 [%2] in product '%3'")
                   .arg(m_artifact->filePath(),
                        m_artifact->fileTags().toStringList().join(QLatin1String(", ")),
                        m_artifact->product->name);
    }

    m_artifact->inputsScanned = true;

    // clear file dependencies; they will be regenerated
    m_artifact->fileDependencies.clear();

    // Remove all connections to children that were added by the dependency scanner.
    // They will be regenerated.
    foreach (Artifact *dependency, m_artifact->childrenAddedByScanner)
        disconnect(m_artifact, dependency, m_logger);

    ArtifactSet::const_iterator it = m_artifact->transformer->inputs.begin();
    for (; it != m_artifact->transformer->inputs.end(); ++it) {
        Artifact *inputArtifact = *it;
        scanForFileDependencies(inputArtifact);
    }
}

void InputArtifactScanner::scanForFileDependencies(Artifact *inputArtifact)
{
    if (m_logger.traceEnabled()) {
        m_logger.qbsTrace()
                << QString::fromLatin1("[DEPSCAN] input artifact %1 [%2]")
                   .arg(inputArtifact->filePath(),
                        inputArtifact->fileTags().toStringList().join(QLatin1String(", ")));
    }

    InputArtifactScannerContext::CacheItem &cacheItem = m_context->cache[inputArtifact->properties];
    QSet<QString> visitedFilePaths;
    QList<FileResourceBase *> filesToScan;
    filesToScan.append(inputArtifact);
    const QSet<DependencyScanner *> scanners = scannersForArtifact(inputArtifact);
    while (!filesToScan.isEmpty()) {
        FileResourceBase *fileToBeScanned = filesToScan.takeFirst();
        const QString &filePathToBeScanned = fileToBeScanned->filePath();
        if (visitedFilePaths.contains(filePathToBeScanned))
            continue;
        visitedFilePaths.insert(filePathToBeScanned);

        foreach (DependencyScanner *scanner, scanners) {
            scanForScannerFileDependencies(scanner, inputArtifact, fileToBeScanned,
                scanner->recursive() ? &filesToScan : 0, cacheItem[scanner->key()]);
        }
    }
}

QSet<DependencyScanner *> InputArtifactScanner::scannersForArtifact(const Artifact *artifact) const
{
    QSet<DependencyScanner *> scanners;
    ResolvedProduct *product = artifact->product.data();
    QHash<FileTag, InputArtifactScannerContext::DependencyScannerCacheItem> &scannerCache
            = m_context->scannersCache[product];
    foreach (const FileTag &fileTag, artifact->fileTags()) {
        InputArtifactScannerContext::DependencyScannerCacheItem &cache = scannerCache[fileTag];
        if (!cache.valid) {
            cache.valid = true;
            foreach (ScannerPlugin *scanner, ScannerPluginManager::scannersForFileTag(fileTag)) {
                PluginDependencyScanner *pluginScanner = new PluginDependencyScanner(scanner);
                cache.scanners += DependencyScannerPtr(pluginScanner);
            }
            foreach (const ResolvedScannerConstPtr &scanner, product->scanners) {
                if (scanner->inputs.contains(fileTag)) {
                    cache.scanners += DependencyScannerPtr(
                                new UserDependencyScanner(scanner, m_logger));
                    break;
                }
            }
        }
        foreach (const DependencyScannerPtr &scanner, cache.scanners) {
            scanners += scanner.data();
        }
    }
    return scanners;
}

void InputArtifactScanner::scanForScannerFileDependencies(DependencyScanner *scanner,
        Artifact *inputArtifact, FileResourceBase *fileToBeScanned,
        QList<FileResourceBase *> *filesToScan,
        InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache)
{
    if (m_logger.traceEnabled()) {
        m_logger.qbsTrace() << QString::fromLatin1("[DEPSCAN] file %1")
                .arg(fileToBeScanned->filePath());
    }

    const bool cacheHit = cache.valid;
    if (!cacheHit) {
        cache.valid = true;
        cache.searchPaths = scanner->collectSearchPaths(inputArtifact);
    }
    if (m_logger.traceEnabled()) {
        m_logger.qbsTrace()
                << "[DEPSCAN] include paths (cache " << (cacheHit ? "hit)" : "miss)");
        foreach (const QString &s, cache.searchPaths)
            m_logger.qbsTrace() << "    " << s;
    }

    const QString &filePathToBeScanned = fileToBeScanned->filePath();
    ScanResultCache::Result scanResult = m_context->scanResultCache->value(scanner->key(), filePathToBeScanned);
    if (!scanResult.valid) {
        try {
            if (m_logger.traceEnabled())
                m_logger.qbsTrace() << "scanning " << FileInfo::fileName(filePathToBeScanned);
            scanWithScannerPlugin(scanner, fileToBeScanned, &scanResult);
        } catch (const ErrorInfo &error) {
            m_logger.printWarning(error);
            return;
        }
        m_context->scanResultCache->insert(scanner->key(), filePathToBeScanned, scanResult);
    }

    resolveScanResultDependencies(inputArtifact, scanResult, filesToScan, cache);
}

void InputArtifactScanner::resolveScanResultDependencies(const Artifact *inputArtifact,
        const ScanResultCache::Result &scanResult, QList<FileResourceBase *> *artifactsToScan,
        InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache)
{
    foreach (const ScanResultCache::Dependency &dependency, scanResult.deps) {
        const QString &dependencyFilePath = dependency.filePath();
        InputArtifactScannerContext::ResolvedDependencyCacheItem &cachedResolvedDependencyItem
                = cache.resolvedDependenciesCache[dependency.dirPath()][dependency.fileName()];
        ResolvedDependency &resolvedDependency = cachedResolvedDependencyItem.resolvedDependency;
        if (cachedResolvedDependencyItem.valid) {
            if (resolvedDependency.filePath.isEmpty())
                goto unresolved;
            goto resolved;
        }
        cachedResolvedDependencyItem.valid = true;

        if (FileInfo::isAbsolute(dependencyFilePath)) {
            resolveAbsolutePath(dependency, inputArtifact->product.data(),
                                &resolvedDependency);
            goto resolved;
        }

        // try include paths
        foreach (const QString &includePath, cache.searchPaths) {
            resolveWithIncludePath(includePath, dependency, inputArtifact->product.data(),
                                   &resolvedDependency);
            if (resolvedDependency.isValid())
                goto resolved;
        }

unresolved:
        if (m_logger.traceEnabled())
            m_logger.qbsWarning() << "[DEPSCAN] unresolved dependency " << dependencyFilePath;
        continue;

resolved:
        handleDependency(resolvedDependency);
        if (artifactsToScan && resolvedDependency.file) {
            if (Artifact *artifactDependency = dynamic_cast<Artifact *>(resolvedDependency.file)) {
                // Do not scan artifacts that are being built. Otherwise we might read an incomplete
                // file or conflict with the writing process.
                if (artifactDependency->buildState != BuildGraphNode::Building)
                    artifactsToScan->append(artifactDependency);
            } else {
                // Add file dependency to the next round of scanning.
                artifactsToScan->append(resolvedDependency.file);
            }
        }
    }
}

void InputArtifactScanner::handleDependency(ResolvedDependency &dependency)
{
    const ResolvedProductPtr product = m_artifact->product;
    QBS_CHECK(m_artifact->artifactType == Artifact::Generated);
    QBS_CHECK(product);

    Artifact *artifactDependency = dynamic_cast<Artifact *>(dependency.file);
    FileDependency *fileDependency
            = artifactDependency ? 0 : dynamic_cast<FileDependency *>(dependency.file);
    QBS_CHECK(!dependency.file || artifactDependency || fileDependency);

    if (!dependency.file) {
        // The dependency is an existing file but does not exist in the build graph.
        if (m_logger.traceEnabled())
            m_logger.qbsTrace() << "[DEPSCAN] add new file dependency " << dependency.filePath;

        fileDependency = new FileDependency();
        dependency.file = fileDependency;
        fileDependency->setFilePath(dependency.filePath);
        product->topLevelProject()->buildData->insertFileDependency(fileDependency);
    } else if (fileDependency) {
        // The dependency exists in the project's list of file dependencies.
        if (m_logger.traceEnabled()) {
            m_logger.qbsTrace() << "[DEPSCAN] add existing file dependency "
                                << dependency.filePath;
        }
    } else if (artifactDependency->product == product) {
        // The dependency is in our product.
        if (m_logger.traceEnabled()) {
            m_logger.qbsTrace() << "[DEPSCAN] add artifact dependency " << dependency.filePath
                                << " (from this product)";
        }
    } else {
        // The dependency is in some other product.
        ResolvedProduct * const otherProduct = artifactDependency->product;
        if (m_logger.traceEnabled()) {
            m_logger.qbsTrace() << "[DEPSCAN] add artifact dependency " << dependency.filePath
                                << " (from product " << otherProduct->uniqueName() << ')';
        }
    }

    if (m_artifact == dependency.file)
        return;

    if (fileDependency) {
        if (!m_artifact->fileDependencies.contains(fileDependency))
            m_artifact->fileDependencies << fileDependency;
    } else {
        if (m_artifact->children.contains(artifactDependency))
            return;
        safeConnect(m_artifact, artifactDependency, m_logger);
        m_artifact->childrenAddedByScanner += artifactDependency;
        m_newDependencyAdded = true;
    }
}

InputArtifactScannerContext::DependencyScannerCacheItem::DependencyScannerCacheItem() : valid(false)
{
}

InputArtifactScannerContext::DependencyScannerCacheItem::~DependencyScannerCacheItem()
{
}

} // namespace Internal
} // namespace qbs
<commit_msg>InputArtifactScanner: Add assertion<commit_after>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "inputartifactscanner.h"

#include "artifact.h"
#include "buildgraph.h"
#include "productbuilddata.h"
#include "projectbuilddata.h"
#include "transformer.h"
#include "depscanner.h"
#include "rulesevaluationcontext.h"

#include <language/language.h>
#include <tools/fileinfo.h>
#include <tools/scannerpluginmanager.h>
#include <tools/qbsassert.h>
#include <tools/error.h>

#include <QDir>
#include <QSet>
#include <QStringList>
#include <QVariantMap>

namespace qbs {
namespace Internal {

InputArtifactScannerContext::InputArtifactScannerContext(ScanResultCache *scanResultCache)
    : scanResultCache(scanResultCache)
{
}

InputArtifactScannerContext::~InputArtifactScannerContext()
{
}

static void resolveWithIncludePath(const QString &includePath,
        const ScanResultCache::Dependency &dependency, const ResolvedProduct *product,
        ResolvedDependency *result)
{
    QString absDirPath = dependency.dirPath().isEmpty() ? includePath : FileInfo::resolvePath(includePath, dependency.dirPath());
    if (!dependency.isClean())
        absDirPath = QDir::cleanPath(absDirPath);

    ResolvedProject *project = product->project.data();
    FileDependency *fileDependencyArtifact = 0;
    Artifact *dependencyInProduct = 0;
    Artifact *dependencyInOtherProduct = 0;
    foreach (FileResourceBase *lookupResult, project->topLevelProject()
             ->buildData->lookupFiles(absDirPath, dependency.fileName())) {
        if ((fileDependencyArtifact = dynamic_cast<FileDependency *>(lookupResult)))
            continue;
        Artifact * const foundArtifact = dynamic_cast<Artifact *>(lookupResult);
        if (foundArtifact->product == product)
            dependencyInProduct = foundArtifact;
        else
            dependencyInOtherProduct = foundArtifact;
    }

    // prioritize found artifacts
    if ((result->file = dependencyInProduct)
        || (result->file = dependencyInOtherProduct)
        || (result->file = fileDependencyArtifact))
    {
        result->filePath = result->file->filePath();
        return;
    }

    QString absFilePath = absDirPath + QLatin1Char('/') + dependency.fileName();

    // TODO: We probably need a flag that tells us whether directories are allowed.
    const FileInfo fi(absFilePath);
    if (fi.exists(absFilePath) && !fi.isDir())
        result->filePath = absFilePath;
}

static void resolveAbsolutePath(const ScanResultCache::Dependency &dependency,
        const ResolvedProduct *product, ResolvedDependency *result)
{
    QString absDirPath = dependency.dirPath();
    if (!dependency.isClean())
        absDirPath = QDir::cleanPath(absDirPath);

    ResolvedProject *project = product->project.data();
    FileDependency *fileDependencyArtifact = 0;
    Artifact *dependencyInProduct = 0;
    Artifact *dependencyInOtherProduct = 0;
    foreach (FileResourceBase *lookupResult, project->topLevelProject()
             ->buildData->lookupFiles(absDirPath, dependency.fileName())) {
        if ((fileDependencyArtifact = dynamic_cast<FileDependency *>(lookupResult)))
            continue;
        Artifact * const foundArtifact = dynamic_cast<Artifact *>(lookupResult);
        if (foundArtifact->product == product)
            dependencyInProduct = foundArtifact;
        else
            dependencyInOtherProduct = foundArtifact;
    }

    // prioritize found artifacts
    if ((result->file = dependencyInProduct)
        || (result->file = dependencyInOtherProduct)
        || (result->file = fileDependencyArtifact)) {
        result->filePath = result->file->filePath();
        return;
    }

    if (FileInfo::exists(dependency.filePath()))
        result->filePath = dependency.filePath();
}

static void scanWithScannerPlugin(DependencyScanner *scanner,
                                  FileResourceBase *fileToBeScanned,
                                  ScanResultCache::Result *scanResult)
{
    QStringList dependencies = scanner->collectDependencies(fileToBeScanned);
    foreach (const QString &s, dependencies)
        scanResult->deps += ScanResultCache::Dependency(s);
    scanResult->valid = true;
}

InputArtifactScanner::InputArtifactScanner(Artifact *artifact, InputArtifactScannerContext *ctx,
                                           const Logger &logger)
    : m_artifact(artifact), m_context(ctx), m_newDependencyAdded(false), m_logger(logger)
{
}

void InputArtifactScanner::scan()
{
    if (m_artifact->inputsScanned)
        return;

    if (m_logger.traceEnabled()) {
        m_logger.qbsTrace()
                << QString::fromLatin1("[DEPSCAN] inputs for %1 [%2] in product '%3'")
                   .arg(m_artifact->filePath(),
                        m_artifact->fileTags().toStringList().join(QLatin1String(", ")),
                        m_artifact->product->name);
    }

    m_artifact->inputsScanned = true;

    // clear file dependencies; they will be regenerated
    m_artifact->fileDependencies.clear();

    // Remove all connections to children that were added by the dependency scanner.
    // They will be regenerated.
    foreach (Artifact *dependency, m_artifact->childrenAddedByScanner)
        disconnect(m_artifact, dependency, m_logger);
    QBS_CHECK(m_artifact->childrenAddedByScanner.isEmpty());

    ArtifactSet::const_iterator it = m_artifact->transformer->inputs.begin();
    for (; it != m_artifact->transformer->inputs.end(); ++it) {
        Artifact *inputArtifact = *it;
        scanForFileDependencies(inputArtifact);
    }
}

void InputArtifactScanner::scanForFileDependencies(Artifact *inputArtifact)
{
    if (m_logger.traceEnabled()) {
        m_logger.qbsTrace()
                << QString::fromLatin1("[DEPSCAN] input artifact %1 [%2]")
                   .arg(inputArtifact->filePath(),
                        inputArtifact->fileTags().toStringList().join(QLatin1String(", ")));
    }

    InputArtifactScannerContext::CacheItem &cacheItem = m_context->cache[inputArtifact->properties];
    QSet<QString> visitedFilePaths;
    QList<FileResourceBase *> filesToScan;
    filesToScan.append(inputArtifact);
    const QSet<DependencyScanner *> scanners = scannersForArtifact(inputArtifact);
    while (!filesToScan.isEmpty()) {
        FileResourceBase *fileToBeScanned = filesToScan.takeFirst();
        const QString &filePathToBeScanned = fileToBeScanned->filePath();
        if (visitedFilePaths.contains(filePathToBeScanned))
            continue;
        visitedFilePaths.insert(filePathToBeScanned);

        foreach (DependencyScanner *scanner, scanners) {
            scanForScannerFileDependencies(scanner, inputArtifact, fileToBeScanned,
                scanner->recursive() ? &filesToScan : 0, cacheItem[scanner->key()]);
        }
    }
}

QSet<DependencyScanner *> InputArtifactScanner::scannersForArtifact(const Artifact *artifact) const
{
    QSet<DependencyScanner *> scanners;
    ResolvedProduct *product = artifact->product.data();
    QHash<FileTag, InputArtifactScannerContext::DependencyScannerCacheItem> &scannerCache
            = m_context->scannersCache[product];
    foreach (const FileTag &fileTag, artifact->fileTags()) {
        InputArtifactScannerContext::DependencyScannerCacheItem &cache = scannerCache[fileTag];
        if (!cache.valid) {
            cache.valid = true;
            foreach (ScannerPlugin *scanner, ScannerPluginManager::scannersForFileTag(fileTag)) {
                PluginDependencyScanner *pluginScanner = new PluginDependencyScanner(scanner);
                cache.scanners += DependencyScannerPtr(pluginScanner);
            }
            foreach (const ResolvedScannerConstPtr &scanner, product->scanners) {
                if (scanner->inputs.contains(fileTag)) {
                    cache.scanners += DependencyScannerPtr(
                                new UserDependencyScanner(scanner, m_logger));
                    break;
                }
            }
        }
        foreach (const DependencyScannerPtr &scanner, cache.scanners) {
            scanners += scanner.data();
        }
    }
    return scanners;
}

void InputArtifactScanner::scanForScannerFileDependencies(DependencyScanner *scanner,
        Artifact *inputArtifact, FileResourceBase *fileToBeScanned,
        QList<FileResourceBase *> *filesToScan,
        InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache)
{
    if (m_logger.traceEnabled()) {
        m_logger.qbsTrace() << QString::fromLatin1("[DEPSCAN] file %1")
                .arg(fileToBeScanned->filePath());
    }

    const bool cacheHit = cache.valid;
    if (!cacheHit) {
        cache.valid = true;
        cache.searchPaths = scanner->collectSearchPaths(inputArtifact);
    }
    if (m_logger.traceEnabled()) {
        m_logger.qbsTrace()
                << "[DEPSCAN] include paths (cache " << (cacheHit ? "hit)" : "miss)");
        foreach (const QString &s, cache.searchPaths)
            m_logger.qbsTrace() << "    " << s;
    }

    const QString &filePathToBeScanned = fileToBeScanned->filePath();
    ScanResultCache::Result scanResult = m_context->scanResultCache->value(scanner->key(), filePathToBeScanned);
    if (!scanResult.valid) {
        try {
            if (m_logger.traceEnabled())
                m_logger.qbsTrace() << "scanning " << FileInfo::fileName(filePathToBeScanned);
            scanWithScannerPlugin(scanner, fileToBeScanned, &scanResult);
        } catch (const ErrorInfo &error) {
            m_logger.printWarning(error);
            return;
        }
        m_context->scanResultCache->insert(scanner->key(), filePathToBeScanned, scanResult);
    }

    resolveScanResultDependencies(inputArtifact, scanResult, filesToScan, cache);
}

void InputArtifactScanner::resolveScanResultDependencies(const Artifact *inputArtifact,
        const ScanResultCache::Result &scanResult, QList<FileResourceBase *> *artifactsToScan,
        InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache)
{
    foreach (const ScanResultCache::Dependency &dependency, scanResult.deps) {
        const QString &dependencyFilePath = dependency.filePath();
        InputArtifactScannerContext::ResolvedDependencyCacheItem &cachedResolvedDependencyItem
                = cache.resolvedDependenciesCache[dependency.dirPath()][dependency.fileName()];
        ResolvedDependency &resolvedDependency = cachedResolvedDependencyItem.resolvedDependency;
        if (cachedResolvedDependencyItem.valid) {
            if (resolvedDependency.filePath.isEmpty())
                goto unresolved;
            goto resolved;
        }
        cachedResolvedDependencyItem.valid = true;

        if (FileInfo::isAbsolute(dependencyFilePath)) {
            resolveAbsolutePath(dependency, inputArtifact->product.data(),
                                &resolvedDependency);
            goto resolved;
        }

        // try include paths
        foreach (const QString &includePath, cache.searchPaths) {
            resolveWithIncludePath(includePath, dependency, inputArtifact->product.data(),
                                   &resolvedDependency);
            if (resolvedDependency.isValid())
                goto resolved;
        }

unresolved:
        if (m_logger.traceEnabled())
            m_logger.qbsWarning() << "[DEPSCAN] unresolved dependency " << dependencyFilePath;
        continue;

resolved:
        handleDependency(resolvedDependency);
        if (artifactsToScan && resolvedDependency.file) {
            if (Artifact *artifactDependency = dynamic_cast<Artifact *>(resolvedDependency.file)) {
                // Do not scan artifacts that are being built. Otherwise we might read an incomplete
                // file or conflict with the writing process.
                if (artifactDependency->buildState != BuildGraphNode::Building)
                    artifactsToScan->append(artifactDependency);
            } else {
                // Add file dependency to the next round of scanning.
                artifactsToScan->append(resolvedDependency.file);
            }
        }
    }
}

void InputArtifactScanner::handleDependency(ResolvedDependency &dependency)
{
    const ResolvedProductPtr product = m_artifact->product;
    QBS_CHECK(m_artifact->artifactType == Artifact::Generated);
    QBS_CHECK(product);

    Artifact *artifactDependency = dynamic_cast<Artifact *>(dependency.file);
    FileDependency *fileDependency
            = artifactDependency ? 0 : dynamic_cast<FileDependency *>(dependency.file);
    QBS_CHECK(!dependency.file || artifactDependency || fileDependency);

    if (!dependency.file) {
        // The dependency is an existing file but does not exist in the build graph.
        if (m_logger.traceEnabled())
            m_logger.qbsTrace() << "[DEPSCAN] add new file dependency " << dependency.filePath;

        fileDependency = new FileDependency();
        dependency.file = fileDependency;
        fileDependency->setFilePath(dependency.filePath);
        product->topLevelProject()->buildData->insertFileDependency(fileDependency);
    } else if (fileDependency) {
        // The dependency exists in the project's list of file dependencies.
        if (m_logger.traceEnabled()) {
            m_logger.qbsTrace() << "[DEPSCAN] add existing file dependency "
                                << dependency.filePath;
        }
    } else if (artifactDependency->product == product) {
        // The dependency is in our product.
        if (m_logger.traceEnabled()) {
            m_logger.qbsTrace() << "[DEPSCAN] add artifact dependency " << dependency.filePath
                                << " (from this product)";
        }
    } else {
        // The dependency is in some other product.
        ResolvedProduct * const otherProduct = artifactDependency->product;
        if (m_logger.traceEnabled()) {
            m_logger.qbsTrace() << "[DEPSCAN] add artifact dependency " << dependency.filePath
                                << " (from product " << otherProduct->uniqueName() << ')';
        }
    }

    if (m_artifact == dependency.file)
        return;

    if (fileDependency) {
        if (!m_artifact->fileDependencies.contains(fileDependency))
            m_artifact->fileDependencies << fileDependency;
    } else {
        if (m_artifact->children.contains(artifactDependency))
            return;
        safeConnect(m_artifact, artifactDependency, m_logger);
        m_artifact->childrenAddedByScanner += artifactDependency;
        m_newDependencyAdded = true;
    }
}

InputArtifactScannerContext::DependencyScannerCacheItem::DependencyScannerCacheItem() : valid(false)
{
}

InputArtifactScannerContext::DependencyScannerCacheItem::~DependencyScannerCacheItem()
{
}

} // namespace Internal
} // namespace qbs
<|endoftext|>


<commit_before>// Copyright (c) 2014 Robert Kooima
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#ifndef GLFRAMEBUFFER_HPP
#define GLFRAMEBUFFER_HPP

#include <exception>

#include "GLFundamentals.hpp"

//------------------------------------------------------------------------------

namespace gl
{
    struct framebuffer
    {
        framebuffer(int w, int h) : width(w), height(h)
        {
            const GLenum F = GL_FRAMEBUFFER;
            const GLenum T = GL_TEXTURE_2D;

            glGenTextures    (1, &color);
            glGenTextures    (1, &depth);
            glGenFramebuffers(1, &frame);

            // Initialize the color buffer.

            glBindTexture(T, color);

            glTexParameteri(T, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(T, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(T, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE);
            glTexParameteri(T, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE);

            glTexImage2D(T, 0, GL_RGBA8, w, h, 0,
                               GL_RGBA, GL_UNSIGNED_BYTE, 0);

            // Initialize the depth buffer.

            glBindTexture(T, depth);

            glTexParameteri(T, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(T, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(T, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE);
            glTexParameteri(T, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE);

            glTexImage2D(T, 0, GL_DEPTH_COMPONENT24, w, h, 0,
                               GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);

            // Initialize the frame buffer.

            glBindFramebuffer(F, frame);

            glFramebufferTexture2D(F, GL_COLOR_ATTACHMENT0, T, color, 0);
            glFramebufferTexture2D(F, GL_DEPTH_ATTACHMENT,  T, depth, 0);

            check();

            // Unbind

            glBindFramebuffer(F, 0);
            glBindTexture    (T, 0);
        }

        ~framebuffer()
        {
            glDeleteFramebuffers(1, &frame);
            glDeleteTextures    (1, &color);
            glDeleteTextures    (1, &depth);
        }

        void check()
        {
            switch (glCheckFramebufferStatus(GL_FRAMEBUFFER))
            {
            case GL_FRAMEBUFFER_COMPLETE:
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
                throw std::runtime_error("Framebuffer incomplete attachment");
            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
                throw std::runtime_error("Framebuffer missing attachment");
            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
                throw std::runtime_error("Framebuffer draw buffer");
            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
                throw std::runtime_error("Framebuffer read buffer");
            case GL_FRAMEBUFFER_UNSUPPORTED:
                throw std::runtime_error("Framebuffer unsupported");
            default:
                throw std::runtime_error("Framebuffer error");
            }
        }

        void bind()
        {
            glBindFramebuffer(GL_FRAMEBUFFER, frame);
            glViewport(0, 0, width, height);
        }

        GLsizei width;
        GLsizei height;
        GLuint  color;
        GLuint  depth;
        GLuint  frame;
    };
}

//------------------------------------------------------------------------------

#endif<commit_msg>Document the framebuffer object<commit_after>// Copyright (c) 2014 Robert Kooima
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#ifndef GLFRAMEBUFFER_HPP
#define GLFRAMEBUFFER_HPP

#include <exception>

#include "GLFundamentals.hpp"

//------------------------------------------------------------------------------

namespace gl
{
    struct framebuffer
    {
        /// Initialize an OpenGL framebuffer object with color and depth.
        ///
        /// @param w  Buffer width
        /// @param h  Buffer height

        framebuffer(int w, int h) : width(w), height(h)
        {
            const GLenum F = GL_FRAMEBUFFER;
            const GLenum T = GL_TEXTURE_2D;

            glGenTextures    (1, &color);
            glGenTextures    (1, &depth);
            glGenFramebuffers(1, &frame);

            // Initialize the color buffer.

            glBindTexture(T, color);

            glTexParameteri(T, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(T, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(T, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE);
            glTexParameteri(T, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE);

            glTexImage2D(T, 0, GL_RGBA8, w, h, 0,
                               GL_RGBA, GL_UNSIGNED_BYTE, 0);

            // Initialize the depth buffer.

            glBindTexture(T, depth);

            glTexParameteri(T, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(T, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(T, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE);
            glTexParameteri(T, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE);

            glTexImage2D(T, 0, GL_DEPTH_COMPONENT24, w, h, 0,
                               GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);

            // Initialize the frame buffer.

            glBindFramebuffer(F, frame);

            glFramebufferTexture2D(F, GL_COLOR_ATTACHMENT0, T, color, 0);
            glFramebufferTexture2D(F, GL_DEPTH_ATTACHMENT,  T, depth, 0);

            check();

            // Unbind

            glBindFramebuffer(F, 0);
            glBindTexture    (T, 0);
        }

        /// Release all OpenGL resources.

        ~framebuffer()
        {
            glDeleteFramebuffers(1, &frame);
            glDeleteTextures    (1, &color);
            glDeleteTextures    (1, &depth);
        }

        /// Query the framebuffer status and throw any incompleteness error.

        void check() const
        {
            switch (glCheckFramebufferStatus(GL_FRAMEBUFFER))
            {
            case GL_FRAMEBUFFER_COMPLETE:
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
                throw std::runtime_error("Framebuffer incomplete attachment");
            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
                throw std::runtime_error("Framebuffer missing attachment");
            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
                throw std::runtime_error("Framebuffer draw buffer");
            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
                throw std::runtime_error("Framebuffer read buffer");
            case GL_FRAMEBUFFER_UNSUPPORTED:
                throw std::runtime_error("Framebuffer unsupported");
            default:
                throw std::runtime_error("Framebuffer error");
            }
        }

        /// Bind hte framebuffer and configure the viewport to fill it.

        void bind() const
        {
            glBindFramebuffer(GL_FRAMEBUFFER, frame);
            glViewport(0, 0, width, height);
        }

        GLsizei width;   ///< Buffer width
        GLsizei height;  ///< Buffer height
        GLuint  color;   ///< Color texture object
        GLuint  depth;   ///< Depth texture object
        GLuint  frame;   ///< Frame buffer object
    };
}

//------------------------------------------------------------------------------

#endif<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmlprofilermodelmanager.h"
#include "qmlprofilerdatamodel.h"
#include "qv8profilerdatamodel.h"
#include "qmlprofilertracefile.h"
#include "notesmodel.h"

#include <utils/qtcassert.h>

#include <QDebug>
#include <QFile>

namespace QmlProfiler {
namespace Internal {

static const char *ProfileFeatureNames[QmlDebug::MaximumProfileFeature] = {
    QT_TRANSLATE_NOOP("MainView", "JavaScript"),
    QT_TRANSLATE_NOOP("MainView", "Memory Usage"),
    QT_TRANSLATE_NOOP("MainView", "Pixmap Cache"),
    QT_TRANSLATE_NOOP("MainView", "Scene Graph"),
    QT_TRANSLATE_NOOP("MainView", "Animations"),
    QT_TRANSLATE_NOOP("MainView", "Painting"),
    QT_TRANSLATE_NOOP("MainView", "Compiling"),
    QT_TRANSLATE_NOOP("MainView", "Creating"),
    QT_TRANSLATE_NOOP("MainView", "Binding"),
    QT_TRANSLATE_NOOP("MainView", "Handling Signal"),
    QT_TRANSLATE_NOOP("MainView", "Input Events")
};

/////////////////////////////////////////////////////////////////////
QmlProfilerDataState::QmlProfilerDataState(QmlProfilerModelManager *modelManager, QObject *parent)
    : QObject(parent), m_state(Empty), m_modelManager(modelManager)
{
    connect(this, SIGNAL(error(QString)), m_modelManager, SIGNAL(error(QString)));
    connect(this, SIGNAL(stateChanged()), m_modelManager, SIGNAL(stateChanged()));
}

void QmlProfilerDataState::setState(QmlProfilerDataState::State state)
{
    // It's not an error, we are continuously calling "AcquiringData" for example
    if (m_state == state)
        return;

    switch (state) {
        case ClearingData:
            QTC_ASSERT(m_state == Done || m_state == Empty || m_state == AcquiringData, /**/);
        break;
        case Empty:
            // if it's not empty, complain but go on
            QTC_ASSERT(m_modelManager->isEmpty(), /**/);
        break;
        case AcquiringData:
            // we're not supposed to receive new data while processing older data
            QTC_ASSERT(m_state != ProcessingData, return);
        break;
        case ProcessingData:
            QTC_ASSERT(m_state == AcquiringData, return);
        break;
        case Done:
            QTC_ASSERT(m_state == ProcessingData || m_state == Empty, return);
        break;
        default:
            emit error(tr("Trying to set unknown state in events list."));
        break;
    }

    m_state = state;
    emit stateChanged();

    return;
}

/////////////////////////////////////////////////////////////////////
QmlProfilerTraceTime::QmlProfilerTraceTime(QObject *parent) :
    QObject(parent), m_startTime(-1), m_endTime(-1)
{
}

QmlProfilerTraceTime::~QmlProfilerTraceTime()
{
}

qint64 QmlProfilerTraceTime::startTime() const
{
    return m_startTime;
}

qint64 QmlProfilerTraceTime::endTime() const
{
    return m_endTime;
}

qint64 QmlProfilerTraceTime::duration() const
{
    return endTime() - startTime();
}

void QmlProfilerTraceTime::clear()
{
    setStartTime(-1);
    setEndTime(-1);
}

void QmlProfilerTraceTime::setStartTime(qint64 time)
{
    if (time != m_startTime) {
        m_startTime = time;
        emit startTimeChanged(time);
    }
}

void QmlProfilerTraceTime::setEndTime(qint64 time)
{
    if (time != m_endTime) {
        m_endTime = time;
        emit endTimeChanged(time);
    }
}

void QmlProfilerTraceTime::decreaseStartTime(qint64 time)
{
    if (m_startTime > time)
        setStartTime(time);
}

void QmlProfilerTraceTime::increaseEndTime(qint64 time)
{
    if (m_endTime < time)
        setEndTime(time);
}

} // namespace Internal

/////////////////////////////////////////////////////////////////////

class QmlProfilerModelManager::QmlProfilerModelManagerPrivate
{
public:
    QmlProfilerModelManagerPrivate(QmlProfilerModelManager *qq) : q(qq) {}
    ~QmlProfilerModelManagerPrivate() {}
    QmlProfilerModelManager *q;

    QmlProfilerDataModel *model;
    QV8ProfilerDataModel *v8Model;
    NotesModel *notesModel;

    QmlProfilerDataState *dataState;
    QmlProfilerTraceTime *traceTime;

    QVector <double> partialCounts;
    QVector <int> partialCountWeights;
    quint64 features;

    int totalWeight;
    double progress;
    double previousProgress;
    qint64 estimatedTime;

    // file to load
    QString fileName;
};

QmlProfilerModelManager::QmlProfilerModelManager(Utils::FileInProjectFinder *finder, QObject *parent) :
    QObject(parent), d(new QmlProfilerModelManagerPrivate(this))
{
    d->totalWeight = 0;
    d->model = new QmlProfilerDataModel(finder, this);
    d->v8Model = new QV8ProfilerDataModel(finder, this);
    d->dataState = new QmlProfilerDataState(this, this);
    d->traceTime = new QmlProfilerTraceTime(this);
    d->notesModel = new NotesModel(this);
    d->notesModel->setModelManager(this);
}

QmlProfilerModelManager::~QmlProfilerModelManager()
{
    delete d;
}

QmlProfilerTraceTime *QmlProfilerModelManager::traceTime() const
{
    return d->traceTime;
}

QmlProfilerDataModel *QmlProfilerModelManager::qmlModel() const
{
    return d->model;
}

QV8ProfilerDataModel *QmlProfilerModelManager::v8Model() const
{
    return d->v8Model;
}

NotesModel *QmlProfilerModelManager::notesModel() const
{
    return d->notesModel;
}

bool QmlProfilerModelManager::isEmpty() const
{
    return d->model->isEmpty() && d->v8Model->isEmpty();
}

int QmlProfilerModelManager::count() const
{
    return d->model->count();
}

double QmlProfilerModelManager::progress() const
{
    return d->progress;
}

int QmlProfilerModelManager::registerModelProxy()
{
    d->partialCounts << 0;
    d->partialCountWeights << 1;
    d->totalWeight++;
    return d->partialCounts.count()-1;
}

void QmlProfilerModelManager::setProxyCountWeight(int proxyId, int weight)
{
    d->totalWeight += weight - d->partialCountWeights[proxyId];
    d->partialCountWeights[proxyId] = weight;
}

void QmlProfilerModelManager::modelProxyCountUpdated(int proxyId, qint64 count, qint64 max)
{
    d->progress -= d->partialCounts[proxyId] * d->partialCountWeights[proxyId] /
            d->totalWeight;

    if (max <= 0)
        d->partialCounts[proxyId] = 1;
    else
        d->partialCounts[proxyId] = (double)count / (double) max;

    d->progress += d->partialCounts[proxyId] * d->partialCountWeights[proxyId] /
            d->totalWeight;

    if (d->progress - d->previousProgress > 0.01) {
        d->previousProgress = d->progress;
        emit progressChanged();
    }
}

void QmlProfilerModelManager::announceFeatures(int proxyId, quint64 features)
{
    Q_UNUSED(proxyId); // Will use that later to optimize the event dispatching on loading.
    if ((features & d->features) != features) {
        d->features |= features;
        emit availableFeaturesChanged(d->features);
    }
}

quint64 QmlProfilerModelManager::availableFeatures()
{
    return d->features;
}

const char *QmlProfilerModelManager::featureName(QmlDebug::ProfileFeature feature)
{
    return ProfileFeatureNames[feature];
}

qint64 QmlProfilerModelManager::estimatedProfilingTime() const
{
    return d->estimatedTime;
}

void QmlProfilerModelManager::newTimeEstimation(qint64 estimation)
{
    d->estimatedTime = estimation;
}

void QmlProfilerModelManager::addQmlEvent(QmlDebug::Message message,
                                          QmlDebug::RangeType rangeType,
                                          int detailType,
                                          qint64 startTime,
                                          qint64 length,
                                          const QString &data,
                                          const QmlDebug::QmlEventLocation &location,
                                          qint64 ndata1,
                                          qint64 ndata2,
                                          qint64 ndata3,
                                          qint64 ndata4,
                                          qint64 ndata5)
{
    // If trace start time was not explicitly set, use the first event
    if (d->traceTime->startTime() == -1)
        d->traceTime->setStartTime(startTime);

    QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/);
    d->model->addQmlEvent(message, rangeType, detailType, startTime, length, data, location,
                          ndata1, ndata2, ndata3, ndata4, ndata5);
}

void QmlProfilerModelManager::addV8Event(int depth, const QString &function, const QString &filename,
                                         int lineNumber, double totalTime, double selfTime)
{
    d->v8Model->addV8Event(depth, function, filename, lineNumber,totalTime, selfTime);
}

void QmlProfilerModelManager::complete()
{
    switch (state()) {
    case QmlProfilerDataState::ProcessingData:
        // Load notes after the timeline models have been initialized.
        d->notesModel->loadData();
        setState(QmlProfilerDataState::Done);
        emit dataAvailable();
        break;
    case QmlProfilerDataState::AcquiringData:
        // If trace end time was not explicitly set, use the last event
        if (d->traceTime->endTime() == 0)
            d->traceTime->setEndTime(d->model->lastTimeMark());
        setState(QmlProfilerDataState::ProcessingData);
        d->model->complete();
        d->v8Model->complete();
        break;
    case QmlProfilerDataState::Empty:
        setState(QmlProfilerDataState::Done);
        break;
    case QmlProfilerDataState::Done:
        break;
    default:
        emit error(tr("Unexpected complete signal in data model."));
        break;
    }
}

void QmlProfilerModelManager::modelProcessingDone()
{
    Q_ASSERT(state() == QmlProfilerDataState::ProcessingData);
    if (d->model->processingDone() && d->v8Model->processingDone())
        complete();
}

void QmlProfilerModelManager::save(const QString &filename)
{
    QFile file(filename);
    if (!file.open(QIODevice::WriteOnly)) {
        emit error(tr("Could not open %1 for writing.").arg(filename));
        return;
    }

    QmlProfilerFileWriter writer;

    d->notesModel->saveData();
    writer.setTraceTime(traceTime()->startTime(), traceTime()->endTime(), traceTime()->duration());
    writer.setV8DataModel(d->v8Model);
    writer.setQmlEvents(d->model->getEventTypes(), d->model->getEvents());
    writer.setNotes(d->model->getEventNotes());
    writer.save(&file);
}

void QmlProfilerModelManager::load(const QString &filename)
{
    d->fileName = filename;
    load();
}

void QmlProfilerModelManager::setFilename(const QString &filename)
{
    d->fileName = filename;
}

void QmlProfilerModelManager::load()
{
    QString filename = d->fileName;

    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        emit error(tr("Could not open %1 for reading.").arg(filename));
        return;
    }

    // erase current
    clear();

    setState(QmlProfilerDataState::AcquiringData);

    QmlProfilerFileReader reader;
    connect(&reader, SIGNAL(error(QString)), this, SIGNAL(error(QString)));
    connect(&reader, SIGNAL(traceStartTime(qint64)), traceTime(), SLOT(setStartTime(qint64)));
    connect(&reader, SIGNAL(traceEndTime(qint64)), traceTime(), SLOT(setEndTime(qint64)));
    reader.setV8DataModel(d->v8Model);
    reader.setQmlDataModel(d->model);
    reader.load(&file);

    complete();
}

void QmlProfilerModelManager::setState(QmlProfilerDataState::State state)
{
    d->dataState->setState(state);
}

QmlProfilerDataState::State QmlProfilerModelManager::state() const
{
    return d->dataState->state();
}

void QmlProfilerModelManager::clear()
{
    setState(QmlProfilerDataState::ClearingData);
    for (int i = 0; i < d->partialCounts.count(); i++)
        d->partialCounts[i] = 0;
    d->progress = 0;
    d->previousProgress = 0;
    d->model->clear();
    d->v8Model->clear();
    d->traceTime->clear();

    setState(QmlProfilerDataState::Empty);
}

void QmlProfilerModelManager::prepareForWriting()
{
    setState(QmlProfilerDataState::AcquiringData);
}

} // namespace QmlProfiler
<commit_msg>QmlProfiler: Properly initialize features bit field<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmlprofilermodelmanager.h"
#include "qmlprofilerdatamodel.h"
#include "qv8profilerdatamodel.h"
#include "qmlprofilertracefile.h"
#include "notesmodel.h"

#include <utils/qtcassert.h>

#include <QDebug>
#include <QFile>

namespace QmlProfiler {
namespace Internal {

static const char *ProfileFeatureNames[QmlDebug::MaximumProfileFeature] = {
    QT_TRANSLATE_NOOP("MainView", "JavaScript"),
    QT_TRANSLATE_NOOP("MainView", "Memory Usage"),
    QT_TRANSLATE_NOOP("MainView", "Pixmap Cache"),
    QT_TRANSLATE_NOOP("MainView", "Scene Graph"),
    QT_TRANSLATE_NOOP("MainView", "Animations"),
    QT_TRANSLATE_NOOP("MainView", "Painting"),
    QT_TRANSLATE_NOOP("MainView", "Compiling"),
    QT_TRANSLATE_NOOP("MainView", "Creating"),
    QT_TRANSLATE_NOOP("MainView", "Binding"),
    QT_TRANSLATE_NOOP("MainView", "Handling Signal"),
    QT_TRANSLATE_NOOP("MainView", "Input Events")
};

/////////////////////////////////////////////////////////////////////
QmlProfilerDataState::QmlProfilerDataState(QmlProfilerModelManager *modelManager, QObject *parent)
    : QObject(parent), m_state(Empty), m_modelManager(modelManager)
{
    connect(this, SIGNAL(error(QString)), m_modelManager, SIGNAL(error(QString)));
    connect(this, SIGNAL(stateChanged()), m_modelManager, SIGNAL(stateChanged()));
}

void QmlProfilerDataState::setState(QmlProfilerDataState::State state)
{
    // It's not an error, we are continuously calling "AcquiringData" for example
    if (m_state == state)
        return;

    switch (state) {
        case ClearingData:
            QTC_ASSERT(m_state == Done || m_state == Empty || m_state == AcquiringData, /**/);
        break;
        case Empty:
            // if it's not empty, complain but go on
            QTC_ASSERT(m_modelManager->isEmpty(), /**/);
        break;
        case AcquiringData:
            // we're not supposed to receive new data while processing older data
            QTC_ASSERT(m_state != ProcessingData, return);
        break;
        case ProcessingData:
            QTC_ASSERT(m_state == AcquiringData, return);
        break;
        case Done:
            QTC_ASSERT(m_state == ProcessingData || m_state == Empty, return);
        break;
        default:
            emit error(tr("Trying to set unknown state in events list."));
        break;
    }

    m_state = state;
    emit stateChanged();

    return;
}

/////////////////////////////////////////////////////////////////////
QmlProfilerTraceTime::QmlProfilerTraceTime(QObject *parent) :
    QObject(parent), m_startTime(-1), m_endTime(-1)
{
}

QmlProfilerTraceTime::~QmlProfilerTraceTime()
{
}

qint64 QmlProfilerTraceTime::startTime() const
{
    return m_startTime;
}

qint64 QmlProfilerTraceTime::endTime() const
{
    return m_endTime;
}

qint64 QmlProfilerTraceTime::duration() const
{
    return endTime() - startTime();
}

void QmlProfilerTraceTime::clear()
{
    setStartTime(-1);
    setEndTime(-1);
}

void QmlProfilerTraceTime::setStartTime(qint64 time)
{
    if (time != m_startTime) {
        m_startTime = time;
        emit startTimeChanged(time);
    }
}

void QmlProfilerTraceTime::setEndTime(qint64 time)
{
    if (time != m_endTime) {
        m_endTime = time;
        emit endTimeChanged(time);
    }
}

void QmlProfilerTraceTime::decreaseStartTime(qint64 time)
{
    if (m_startTime > time)
        setStartTime(time);
}

void QmlProfilerTraceTime::increaseEndTime(qint64 time)
{
    if (m_endTime < time)
        setEndTime(time);
}

} // namespace Internal

/////////////////////////////////////////////////////////////////////

class QmlProfilerModelManager::QmlProfilerModelManagerPrivate
{
public:
    QmlProfilerModelManagerPrivate(QmlProfilerModelManager *qq) : q(qq) {}
    ~QmlProfilerModelManagerPrivate() {}
    QmlProfilerModelManager *q;

    QmlProfilerDataModel *model;
    QV8ProfilerDataModel *v8Model;
    NotesModel *notesModel;

    QmlProfilerDataState *dataState;
    QmlProfilerTraceTime *traceTime;

    QVector <double> partialCounts;
    QVector <int> partialCountWeights;
    quint64 features;

    int totalWeight;
    double progress;
    double previousProgress;
    qint64 estimatedTime;

    // file to load
    QString fileName;
};

QmlProfilerModelManager::QmlProfilerModelManager(Utils::FileInProjectFinder *finder, QObject *parent) :
    QObject(parent), d(new QmlProfilerModelManagerPrivate(this))
{
    d->totalWeight = 0;
    d->features = 0;
    d->model = new QmlProfilerDataModel(finder, this);
    d->v8Model = new QV8ProfilerDataModel(finder, this);
    d->dataState = new QmlProfilerDataState(this, this);
    d->traceTime = new QmlProfilerTraceTime(this);
    d->notesModel = new NotesModel(this);
    d->notesModel->setModelManager(this);
}

QmlProfilerModelManager::~QmlProfilerModelManager()
{
    delete d;
}

QmlProfilerTraceTime *QmlProfilerModelManager::traceTime() const
{
    return d->traceTime;
}

QmlProfilerDataModel *QmlProfilerModelManager::qmlModel() const
{
    return d->model;
}

QV8ProfilerDataModel *QmlProfilerModelManager::v8Model() const
{
    return d->v8Model;
}

NotesModel *QmlProfilerModelManager::notesModel() const
{
    return d->notesModel;
}

bool QmlProfilerModelManager::isEmpty() const
{
    return d->model->isEmpty() && d->v8Model->isEmpty();
}

int QmlProfilerModelManager::count() const
{
    return d->model->count();
}

double QmlProfilerModelManager::progress() const
{
    return d->progress;
}

int QmlProfilerModelManager::registerModelProxy()
{
    d->partialCounts << 0;
    d->partialCountWeights << 1;
    d->totalWeight++;
    return d->partialCounts.count()-1;
}

void QmlProfilerModelManager::setProxyCountWeight(int proxyId, int weight)
{
    d->totalWeight += weight - d->partialCountWeights[proxyId];
    d->partialCountWeights[proxyId] = weight;
}

void QmlProfilerModelManager::modelProxyCountUpdated(int proxyId, qint64 count, qint64 max)
{
    d->progress -= d->partialCounts[proxyId] * d->partialCountWeights[proxyId] /
            d->totalWeight;

    if (max <= 0)
        d->partialCounts[proxyId] = 1;
    else
        d->partialCounts[proxyId] = (double)count / (double) max;

    d->progress += d->partialCounts[proxyId] * d->partialCountWeights[proxyId] /
            d->totalWeight;

    if (d->progress - d->previousProgress > 0.01) {
        d->previousProgress = d->progress;
        emit progressChanged();
    }
}

void QmlProfilerModelManager::announceFeatures(int proxyId, quint64 features)
{
    Q_UNUSED(proxyId); // Will use that later to optimize the event dispatching on loading.
    if ((features & d->features) != features) {
        d->features |= features;
        emit availableFeaturesChanged(d->features);
    }
}

quint64 QmlProfilerModelManager::availableFeatures()
{
    return d->features;
}

const char *QmlProfilerModelManager::featureName(QmlDebug::ProfileFeature feature)
{
    return ProfileFeatureNames[feature];
}

qint64 QmlProfilerModelManager::estimatedProfilingTime() const
{
    return d->estimatedTime;
}

void QmlProfilerModelManager::newTimeEstimation(qint64 estimation)
{
    d->estimatedTime = estimation;
}

void QmlProfilerModelManager::addQmlEvent(QmlDebug::Message message,
                                          QmlDebug::RangeType rangeType,
                                          int detailType,
                                          qint64 startTime,
                                          qint64 length,
                                          const QString &data,
                                          const QmlDebug::QmlEventLocation &location,
                                          qint64 ndata1,
                                          qint64 ndata2,
                                          qint64 ndata3,
                                          qint64 ndata4,
                                          qint64 ndata5)
{
    // If trace start time was not explicitly set, use the first event
    if (d->traceTime->startTime() == -1)
        d->traceTime->setStartTime(startTime);

    QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/);
    d->model->addQmlEvent(message, rangeType, detailType, startTime, length, data, location,
                          ndata1, ndata2, ndata3, ndata4, ndata5);
}

void QmlProfilerModelManager::addV8Event(int depth, const QString &function, const QString &filename,
                                         int lineNumber, double totalTime, double selfTime)
{
    d->v8Model->addV8Event(depth, function, filename, lineNumber,totalTime, selfTime);
}

void QmlProfilerModelManager::complete()
{
    switch (state()) {
    case QmlProfilerDataState::ProcessingData:
        // Load notes after the timeline models have been initialized.
        d->notesModel->loadData();
        setState(QmlProfilerDataState::Done);
        emit dataAvailable();
        break;
    case QmlProfilerDataState::AcquiringData:
        // If trace end time was not explicitly set, use the last event
        if (d->traceTime->endTime() == 0)
            d->traceTime->setEndTime(d->model->lastTimeMark());
        setState(QmlProfilerDataState::ProcessingData);
        d->model->complete();
        d->v8Model->complete();
        break;
    case QmlProfilerDataState::Empty:
        setState(QmlProfilerDataState::Done);
        break;
    case QmlProfilerDataState::Done:
        break;
    default:
        emit error(tr("Unexpected complete signal in data model."));
        break;
    }
}

void QmlProfilerModelManager::modelProcessingDone()
{
    Q_ASSERT(state() == QmlProfilerDataState::ProcessingData);
    if (d->model->processingDone() && d->v8Model->processingDone())
        complete();
}

void QmlProfilerModelManager::save(const QString &filename)
{
    QFile file(filename);
    if (!file.open(QIODevice::WriteOnly)) {
        emit error(tr("Could not open %1 for writing.").arg(filename));
        return;
    }

    QmlProfilerFileWriter writer;

    d->notesModel->saveData();
    writer.setTraceTime(traceTime()->startTime(), traceTime()->endTime(), traceTime()->duration());
    writer.setV8DataModel(d->v8Model);
    writer.setQmlEvents(d->model->getEventTypes(), d->model->getEvents());
    writer.setNotes(d->model->getEventNotes());
    writer.save(&file);
}

void QmlProfilerModelManager::load(const QString &filename)
{
    d->fileName = filename;
    load();
}

void QmlProfilerModelManager::setFilename(const QString &filename)
{
    d->fileName = filename;
}

void QmlProfilerModelManager::load()
{
    QString filename = d->fileName;

    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        emit error(tr("Could not open %1 for reading.").arg(filename));
        return;
    }

    // erase current
    clear();

    setState(QmlProfilerDataState::AcquiringData);

    QmlProfilerFileReader reader;
    connect(&reader, SIGNAL(error(QString)), this, SIGNAL(error(QString)));
    connect(&reader, SIGNAL(traceStartTime(qint64)), traceTime(), SLOT(setStartTime(qint64)));
    connect(&reader, SIGNAL(traceEndTime(qint64)), traceTime(), SLOT(setEndTime(qint64)));
    reader.setV8DataModel(d->v8Model);
    reader.setQmlDataModel(d->model);
    reader.load(&file);

    complete();
}

void QmlProfilerModelManager::setState(QmlProfilerDataState::State state)
{
    d->dataState->setState(state);
}

QmlProfilerDataState::State QmlProfilerModelManager::state() const
{
    return d->dataState->state();
}

void QmlProfilerModelManager::clear()
{
    setState(QmlProfilerDataState::ClearingData);
    for (int i = 0; i < d->partialCounts.count(); i++)
        d->partialCounts[i] = 0;
    d->progress = 0;
    d->previousProgress = 0;
    d->model->clear();
    d->v8Model->clear();
    d->traceTime->clear();

    setState(QmlProfilerDataState::Empty);
}

void QmlProfilerModelManager::prepareForWriting()
{
    setState(QmlProfilerDataState::AcquiringData);
}

} // namespace QmlProfiler
<|endoftext|>


<commit_before>#ifndef ALEPH_DISTANCES_DETAIL_MUNKRES_HH__
#define ALEPH_DISTANCES_DETAIL_MUNKRES_HH__

#include "Matrix.hh"

#include <algorithm>
#include <limits>
#include <vector>

namespace aleph
{

namespace distances
{

namespace detail
{

template <class T> class Munkres
{
public:

  void solve( Matrix<T>& matrix )
  {
    auto n = matrix.n();

    // Copy input matrix
    this->matrix = m;

    _rowMask = std::vector<bool>( size, false );
    _colMask = std::vector<bool>( size, false );

    subtractRowMinimum( matrix );

    unsigned short step = 1;

    while( step )
    {
      std::size_t row = 0;
      std::size_t col = 0;

      switch ( step ) {
        case 1:
          step = step1( matrix );
          break;
        case 2:
          step = step2( matrix );
          break;
        case 3:
          step = step3( matrix, row, col );
          break;
        case 4:
          step = step4( matrix );
          break;
        case 5:
          step = step5( matrix );
          break;
      }
    }

    for( std::size_t row = 0; row < n; row++ )
    {
      for( std::size_t col = 0; col < n; col++ )
      {
        if( _stars( row, col ) )
          matrix( row, col ) = T( 0 );
        else
          matrix( row, col ) = std::numeric_limits<T>::max();
      }
    }
  }

private:

  // Modifies matrix in-place by subtracting the minimum value in each
  // row. The function assumes that matrix is not empty.
  void subtractRowMinimum( Matrix<T>& matrix )
  {
    auto n = matrix.n();

    for( std::size_t row = 0; row < n; row++ )
    {
      auto min = matrix( row, 0 );

      for( std::size_t col = 0; col < n; col++ )
        min = std::min( min, matrix( row, col ) );

      for( std::size_t col = 0; col < n; col++ )
        matrix( row, col ) -= min;
    }
  }

  bool findUncoveredZeroInMatrix( const Matrix<T>& matrix, std::size_t& row, std::size_t& column ) const
  {
    auto n = matrix.n();

    for( row = 0; row < n; row++ )
    {
      if( !_rowMask[row] )
      {
        for( col = 0; col < n; col++ )
        {
          if( !_colMask[col] )
          {
            if( matrix( row, col ) == T( 0 ) )
              return true;
          }
        }
      }
    }

    return false;
  }

  // Find zeroes in the current matrix. If there is no starred zero in
  // the row or column, star the current value.
  unsigned short step1( Matrix<T>& matrix )
  {
    auto n = matrix.n();

    for( std::size_t row = 0; row < n; row++ )
    {
      for( std::size_t col = 0; col < n; col++ )
      {
        if( matrix( row, col ) == T( 0 ) )
        {
          // Check whether another zero in the same _column_ is already
          // starred.
          for( std::size_t r = 0; r < n; r++ )
          {
            if( _stars( r, col ) )
              goto skipCurrentColumn;
          }

          // Check whether another zero in the same _row_ is already
          // starred.
          for( std::size_t c = 0; c < n; c++ )
          {
            if( _stars( row, c ) )
              goto skipCurrentRow;
          }

          _stars( row, col )  = true;
          _primes( row, col ) = false;
        }
        skipCurrentColumn:
          ;
      }

      skipCurrentRow:
        ;
    }

    return 2;
  }

  // Cover each column that contains a starred zero. If enough columns
  // have been covered, the starred zeroes give us the complete set of
  // assignments.
  unsigned short step2( Matrix<T>& matrix )
  {
    auto n                     = matrix.n();
    std::size_t coveredColumns = 0;

    for( std::size_t row = 0; row < n; row++ )
    {
      for( std::size_t col = 0; col < n; col++ )
      {
        if( _stars( row, col ) )
        {
          _colMask[col] = true;
          ++coveredColumns;
        }
      }
    }

    if( coveredColumns >= n )
      return 0;

    return 3;
  }

  // Find an uncovered zero and prime it. If there is no starred zero in
  // the row containing this primed zero, go to step 5. Otherwise, cover
  // this row and uncover the column that contains the starred zero.
  unsigned short step3( Matrix<T>& matrix, std::size_t& row, std::size_t& col )
  {
    if( findUncoveredZeroInMatrix( matrix, row, col ) )
    {
      _primes( row, col ) = true;
      _stars( row, col )  = false;
    }
    else
      return 5;

    auto n = matrix.n();

    for( std::size_t c = 0; c < n; c++ )
    {
      if( _stars( row, c ) )
      {
        _rowMask[row] = true;
        _colMask[col] = false;

        return 3;
      }
    }

    return 4;
  }

  unsigned short step4( Matrix<T>& matrix, std::size_t row, std::size_t col )
  {
    auto n = matrix.n();

    using Pair     = std::pair<std::size_t, std::size_t>;
    using Sequence = std::vector<Pair>;

    Sequence sequence;

    sequence.push_back( std::make_pair( row, col ) );

    Pair p1 = std::make_pair( 0, 0 );
    Pair p2 = std::make_pair( 0, 0 );

    std::size_t r = 0;
    std::size_t c = col;

    size_t row, col = savecol;

    bool havePair = false;
    do
    {
      havePair = false;
      for ( r = 0; r < n; r++ )
      {
        if( _stars(r,c) )
        {
          p1.first  = r;
          p1.second = c;

          if( std::find( sequence.begin(), sequence.end(), p1 ) != sequence.end() )
            continue;

          havePair = true;

          sequence.push_back( p1 );
          break;
        }
      }

      if( !havePair )
        break;

      havePair = false;

      for( c = 0; c < n; c++ )
      {
        if( _primes(r,c) )
        {
          p2.first  = r;
          p2.second = c;

          if( std::find( sequence.begin(), sequence.end(), p2 ) != sequence.end() )
            continue;

          havePair = true;

          sequence.push_back( p2 );
          break;
        }
      }
    }
    while ( havePair );

    for( auto&& pair : sequence )
    {
      // Un-star
      if( _stars(pair.first, pair.second) )
        _stars(pair.first, pair.second) = false;

      // Star each primed zero
      if( _primes(pair.first, pair.second) )
        _stars(pair.first, pair.second) = true;
    }

    // Erase all primes & uncover all columns and rows -----------------

    for( std::size_t row = 0; row < n; row++ )
    {
      for( std::size_t col = 0; col < n; col++ )
        _primes(row, col) = false;

      _rowMask[row] = false;
      _colMask[row] = false;
    }

    return 2;
  }

  unsigned short step5( Matrix<T>& matrix )
  {
    auto n = matrix.n();
    T v    = std::numeric_limits<T>::max();

    for( std::size_t row = 0; row < n; row++ )
    {
      if( !_rowMask[row] )
      {
        for( std::size_t col = 0; col < n; col++ )
        {
          if( !_colMask[col] )
            if( matrix( row, col ) != T( 0 ) && matrix( row, col ) < v )
              v = matrix( row, col );
        }
      }
    }

    for( std::size_t row = 0; row < n; row++ )
    {
      if( _rowMask[row] )
      {
        for( std::size_t col = 0; col < n; col++ )
          matrix( row, col ) += v;
      }
    }

    for( std::size_t col = 0; col < n; col++ )
    {
      if( !_colMask[col] )
      {
        for( std::size_t row = 0; row < n; row++ )
          matrix( row, col ) -= v;
      }
    }

    return 3;
  }

  Matrix<bool> _stars;
  Matrix<bool> _primes;

  std::vector<bool> _rowMask;
  std::vector<bool> _colMask;
};

}

}

}

#endif
<commit_msg>Fixed remnants of old code for Hungarian method<commit_after>#ifndef ALEPH_DISTANCES_DETAIL_MUNKRES_HH__
#define ALEPH_DISTANCES_DETAIL_MUNKRES_HH__

#include "Matrix.hh"

#include <algorithm>
#include <limits>
#include <vector>

namespace aleph
{

namespace distances
{

namespace detail
{

template <class T> class Munkres
{
public:

  void solve( Matrix<T>& matrix )
  {
    auto n = matrix.n();

    _rowMask = std::vector<bool>( n, false );
    _colMask = std::vector<bool>( n, false );

    subtractRowMinimum( matrix );

    unsigned short step = 1;

    while( step )
    {
      std::size_t row = 0;
      std::size_t col = 0;

      switch ( step ) {
        case 1:
          step = step1( matrix );
          break;
        case 2:
          step = step2( matrix );
          break;
        case 3:
          step = step3( matrix, row, col );
          break;
        case 4:
          step = step4( matrix );
          break;
        case 5:
          step = step5( matrix );
          break;
      }
    }

    for( std::size_t row = 0; row < n; row++ )
    {
      for( std::size_t col = 0; col < n; col++ )
      {
        if( _stars( row, col ) )
          matrix( row, col ) = T( 0 );
        else
          matrix( row, col ) = std::numeric_limits<T>::max();
      }
    }
  }

private:

  // Modifies matrix in-place by subtracting the minimum value in each
  // row. The function assumes that matrix is not empty.
  void subtractRowMinimum( Matrix<T>& matrix )
  {
    auto n = matrix.n();

    for( std::size_t row = 0; row < n; row++ )
    {
      auto min = matrix( row, 0 );

      for( std::size_t col = 0; col < n; col++ )
        min = std::min( min, matrix( row, col ) );

      for( std::size_t col = 0; col < n; col++ )
        matrix( row, col ) -= min;
    }
  }

  bool findUncoveredZeroInMatrix( const Matrix<T>& matrix, std::size_t& row, std::size_t& col ) const
  {
    auto n = matrix.n();

    for( row = 0; row < n; row++ )
    {
      if( !_rowMask[row] )
      {
        for( col = 0; col < n; col++ )
        {
          if( !_colMask[col] )
          {
            if( matrix( row, col ) == T( 0 ) )
              return true;
          }
        }
      }
    }

    return false;
  }

  // Find zeroes in the current matrix. If there is no starred zero in
  // the row or column, star the current value.
  unsigned short step1( Matrix<T>& matrix )
  {
    auto n = matrix.n();

    for( std::size_t row = 0; row < n; row++ )
    {
      for( std::size_t col = 0; col < n; col++ )
      {
        if( matrix( row, col ) == T( 0 ) )
        {
          // Check whether another zero in the same _column_ is already
          // starred.
          for( std::size_t r = 0; r < n; r++ )
          {
            if( _stars( r, col ) )
              goto skipCurrentColumn;
          }

          // Check whether another zero in the same _row_ is already
          // starred.
          for( std::size_t c = 0; c < n; c++ )
          {
            if( _stars( row, c ) )
              goto skipCurrentRow;
          }

          _stars( row, col )  = true;
          _primes( row, col ) = false;
        }
        skipCurrentColumn:
          ;
      }

      skipCurrentRow:
        ;
    }

    return 2;
  }

  // Cover each column that contains a starred zero. If enough columns
  // have been covered, the starred zeroes give us the complete set of
  // assignments.
  unsigned short step2( Matrix<T>& matrix )
  {
    auto n                     = matrix.n();
    std::size_t coveredColumns = 0;

    for( std::size_t row = 0; row < n; row++ )
    {
      for( std::size_t col = 0; col < n; col++ )
      {
        if( _stars( row, col ) )
        {
          _colMask[col] = true;
          ++coveredColumns;
        }
      }
    }

    if( coveredColumns >= n )
      return 0;

    return 3;
  }

  // Find an uncovered zero and prime it. If there is no starred zero in
  // the row containing this primed zero, go to step 5. Otherwise, cover
  // this row and uncover the column that contains the starred zero.
  unsigned short step3( Matrix<T>& matrix, std::size_t& row, std::size_t& col )
  {
    if( findUncoveredZeroInMatrix( matrix, row, col ) )
    {
      _primes( row, col ) = true;
      _stars( row, col )  = false;
    }
    else
      return 5;

    auto n = matrix.n();

    for( std::size_t c = 0; c < n; c++ )
    {
      if( _stars( row, c ) )
      {
        _rowMask[row] = true;
        _colMask[col] = false;

        return 3;
      }
    }

    return 4;
  }

  unsigned short step4( Matrix<T>& matrix, std::size_t row, std::size_t col )
  {
    auto n = matrix.n();

    using Pair     = std::pair<std::size_t, std::size_t>;
    using Sequence = std::vector<Pair>;

    Sequence sequence;

    sequence.push_back( std::make_pair( row, col ) );

    Pair p1 = std::make_pair( 0, 0 );
    Pair p2 = std::make_pair( 0, 0 );

    std::size_t r = 0;
    std::size_t c = col;

    bool havePair = false;

    do
    {
      havePair = false;
      for ( r = 0; r < n; r++ )
      {
        if( _stars(r,c) )
        {
          p1.first  = r;
          p1.second = c;

          if( std::find( sequence.begin(), sequence.end(), p1 ) != sequence.end() )
            continue;

          havePair = true;

          sequence.push_back( p1 );
          break;
        }
      }

      if( !havePair )
        break;

      havePair = false;

      for( c = 0; c < n; c++ )
      {
        if( _primes(r,c) )
        {
          p2.first  = r;
          p2.second = c;

          if( std::find( sequence.begin(), sequence.end(), p2 ) != sequence.end() )
            continue;

          havePair = true;

          sequence.push_back( p2 );
          break;
        }
      }
    }
    while ( havePair );

    for( auto&& pair : sequence )
    {
      // Un-star
      if( _stars(pair.first, pair.second) )
        _stars(pair.first, pair.second) = false;

      // Star each primed zero
      if( _primes(pair.first, pair.second) )
        _stars(pair.first, pair.second) = true;
    }

    // Erase all primes & uncover all columns and rows -----------------

    for( std::size_t row = 0; row < n; row++ )
    {
      for( std::size_t col = 0; col < n; col++ )
        _primes(row, col) = false;

      _rowMask[row] = false;
      _colMask[row] = false;
    }

    return 2;
  }

  unsigned short step5( Matrix<T>& matrix )
  {
    auto n = matrix.n();
    T v    = std::numeric_limits<T>::max();

    for( std::size_t row = 0; row < n; row++ )
    {
      if( !_rowMask[row] )
      {
        for( std::size_t col = 0; col < n; col++ )
        {
          if( !_colMask[col] )
            if( matrix( row, col ) != T( 0 ) && matrix( row, col ) < v )
              v = matrix( row, col );
        }
      }
    }

    for( std::size_t row = 0; row < n; row++ )
    {
      if( _rowMask[row] )
      {
        for( std::size_t col = 0; col < n; col++ )
          matrix( row, col ) += v;
      }
    }

    for( std::size_t col = 0; col < n; col++ )
    {
      if( !_colMask[col] )
      {
        for( std::size_t row = 0; row < n; row++ )
          matrix( row, col ) -= v;
      }
    }

    return 3;
  }

  Matrix<bool> _stars;
  Matrix<bool> _primes;

  std::vector<bool> _rowMask;
  std::vector<bool> _colMask;
};

}

}

}

#endif
<|endoftext|>