<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSCriptTools module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "jsdebuggeragent.h"

#include <QtCore/qcoreapplication.h>
#include <QtCore/qset.h>
#include <QtScript/qscriptengine.h>
#include <QtScript/QScriptContextInfo>
#include <QtCore/QDebug>
#include <QtCore/QUrl>
#include <QtCore/QDateTime>
#include <QtScript/qscriptvalueiterator.h>

QT_BEGIN_NAMESPACE

struct JSAgentWatchData {
    QByteArray exp;
    QString name;
    QString value;
    QString type;
    bool hasChildren;
    quint64 objectId;

    static JSAgentWatchData fromScriptValue(const QString &expression, const QScriptValue &value)
    {
        JSAgentWatchData data;
        data.exp = expression.toUtf8();
        data.name = expression;
        data.hasChildren = false;
        data.value = value.toString();
        data.objectId = value.objectId();
        if (value.isArray()) {
            data.type = QLatin1String("Array");
            data.value = QString::fromLatin1("[Array of length %1]").arg(value.property("length").toString());
            data.hasChildren = true;
        } else if (value.isBool()) {
            data.type = QLatin1String("Bool");
//            data.value = value.toBool() ? QLatin1String("true") : QLatin1String("false");
        } else if (value.isDate()) {
            data.type = QLatin1String("Date");
            data.value = value.toDateTime().toString();
        } else if (value.isError()) {
            data.type = QLatin1String("Error");
        } else if (value.isFunction()) {
            data.type = QLatin1String("Function");
        } else if (value.isUndefined()) {
            data.type = QLatin1String("<undefined>");
        } else if (value.isNumber()) {
            data.type = QLatin1String("Number");
        } else if (value.isRegExp()) {
            data.type = QLatin1String("RegExp");
        } else if (value.isString()) {
            data.type = QLatin1String("String");
        } else if (value.isVariant()) {
            data.type = QLatin1String("Variant");
        } else if (value.isObject()) {
            data.type = QLatin1String("Object");
            data.hasChildren = true;
            data.value = QLatin1String("[Object]");
/*        } else if (value.isQMetaObject()) {
            data.setType(QLatin1String("QMetaObject"), false);
            data.setValue(QString(QLatin1Char(' ')));
        } else if (value.isQObject()) {
            data.type = QLatin1String("QObject");
            data.hasChildren = true;*/
        } else if (value.isNull()) {
            data.type = QLatin1String("<null>");
        } else {
            data.type = QLatin1String("<unknown>");
        }
        return data;
    }
};

QDataStream& operator<<(QDataStream& s, const JSAgentWatchData& data)
{
    return s << data.exp << data.name << data.value << data.type << data.hasChildren << data.objectId;
}

static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
{
    QList<JSAgentWatchData> result;
    QScriptValueIterator it(object);
    while (it.hasNext()) {
        it.next();
        result << JSAgentWatchData::fromScriptValue(it.name(), it.value());
    }
    return result;
}

void JSDebuggerAgent::recordKnownObjects(const QList<JSAgentWatchData>& list)
{
    foreach (const JSAgentWatchData &data, list)
        knownObjectIds << data.objectId;
}

/*!
  Constructs a new agent for the given \a engine. The agent will
  report debugging-related events (e.g. step completion) to the given
  \a backend.
*/
JSDebuggerAgent::JSDebuggerAgent(QScriptEngine *engine)
    : QDeclarativeDebugService("JSDebugger"), QScriptEngineAgent(engine)
{}

/*!
  Destroys this QScriptDebuggerAgent.
*/
JSDebuggerAgent::~JSDebuggerAgent()
{}

/*!
  \reimp
*/
void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
                                      const QString &fileName, int )
{
    Q_UNUSED(program);
    filenames.insert(id, QUrl(fileName).toLocalFile());
}

/*!
  \reimp
*/
void JSDebuggerAgent::scriptUnload(qint64 id)
{
    filenames.remove(id);
}

/*!
  \reimp
*/
void JSDebuggerAgent::contextPush()
{
}

/*!
  \reimp
*/
void JSDebuggerAgent::contextPop()
{
}

/*!
  \reimp
*/
void JSDebuggerAgent::functionEntry(qint64 scriptId)
{
    Q_UNUSED(scriptId);
    stepDepth++;
}

/*!
  \reimp
*/
void JSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(returnValue);
    stepDepth--;
}

/*!
  \reimp
*/
void JSDebuggerAgent::positionChange(qint64 scriptId,
                                   int lineNumber, int columnNumber)
{
    Q_UNUSED(columnNumber);

    if(state == Stopped)
        return; //no re-entrency

    // check breakpoints
    if (!breakpointList.isEmpty()) {
        QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
        if (it == filenames.constEnd()) {
            // It is possible that the scripts are loaded before the agent is attached
            QString filename = QUrl(QScriptContextInfo(engine()->currentContext()).fileName()).toLocalFile();
            QPair<QString, qint32> key = qMakePair(filename, lineNumber);
            it = filenames.insert(scriptId, filename);
        }
        QPair<QString, qint32> key = qMakePair(*it, lineNumber);
        if (breakpointList.contains(key)) {
            stopped();
            return;
        }
    }

    switch (state) {
    case NoState:
    case Stopped:
        // Do nothing
        break;

    case SteppingOutState:
        if (stepDepth >= 0)
            break;
        //fallthough
    case SteppingOverState:
        if (stepDepth > 0)
            break;
        //fallthough
    case SteppingIntoState:
        stopped();
        break;
    }

}

/*!
  \reimp
*/
void JSDebuggerAgent::exceptionThrow(qint64 scriptId,
                                   const QScriptValue &exception,
                                   bool hasHandler)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(exception);
    Q_UNUSED(hasHandler);
/* ... */
}

/*!
  \reimp
*/
void JSDebuggerAgent::exceptionCatch(qint64 scriptId,
                                          const QScriptValue &exception)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(exception);
}

void JSDebuggerAgent::messageReceived(const QByteArray& message)
{
    QDataStream ds(message);
    QByteArray command;
    ds >> command;
    if (command == "BREAKPOINTS") {
        ds >> breakpointList;
    } else if (command == "WATCH_EXPRESSIONS") {
        ds >> watchExpressions;
    } else if (command == "STEPOVER") {
        stepDepth = 0;
        state = SteppingOverState;
        continueExec();
    } else if (command == "STEPINTO" || command == "INTERRUPT") {
        stepDepth = 0;
        state = SteppingIntoState;
        continueExec();
    } else if (command == "STEPOUT") {
        stepDepth = 0;
        state = SteppingOutState;
        continueExec();
    } else if (command == "CONTINUE") {
        state = NoState;
        continueExec();
    } else if (command == "EXEC") {
        State oldState = state;
        state = Stopped;
        QByteArray id;
        QString expr;
        ds >> id >> expr;

        JSAgentWatchData data = JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr));
        knownObjectIds << data.objectId;
        // Clear any exceptions occurred during locals evaluation.
        engine()->clearExceptions();

        QByteArray reply;
        QDataStream rs(&reply, QIODevice::WriteOnly);
        rs << QByteArray("RESULT") << id << data;
        sendMessage(reply);
        state = oldState;
    } else if (command == "EXPAND") {
        State oldState = state;
        state = Stopped;
        QByteArray requestId;
        quint64 objectId;
        ds >> requestId >> objectId;
        QScriptValue v;
        if (knownObjectIds.contains(objectId))
            v = engine()->objectById(objectId);

        QList<JSAgentWatchData> result = expandObject(v);
        recordKnownObjects(result);

        // Clear any exceptions occurred during locals evaluation.
        engine()->clearExceptions();

        QByteArray reply;
        QDataStream rs(&reply, QIODevice::WriteOnly);
        rs << QByteArray("EXPANDED") << requestId << result;
        sendMessage(reply);
        state = oldState;
    } else if (command == "ACTIVATE_FRAME") {
        State oldState = state;
        state = Stopped;

        int frameId;
        ds >> frameId;

        int deep = 0;
        QScriptContext *ctx = engine()->currentContext();
        while (ctx && deep < frameId) {
            ctx = ctx->parentContext();
            deep++;
        }

        QList<JSAgentWatchData> locals;
        if (ctx)
            locals = expandObject(ctx->activationObject());
        recordKnownObjects(locals);

        // Clear any exceptions occurred during locals evaluation.
        engine()->clearExceptions();

        QByteArray reply;
        QDataStream rs(&reply, QIODevice::WriteOnly);
        rs << QByteArray("LOCALS") << frameId << locals;
        sendMessage(reply);
    } else {
        qDebug() << Q_FUNC_INFO << "Unknown command" << command;
    }

    QDeclarativeDebugService::messageReceived(message);
}

void JSDebuggerAgent::stopped()
{
    knownObjectIds.clear();
    state = Stopped;
    QList<QPair<QString, QPair<QString, qint32> > > backtrace;

    for (QScriptContext* ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
        QScriptContextInfo info(ctx);

        QString functionName = info.functionName();
        if (functionName.isEmpty()) {
            if (ctx->parentContext()) {
                switch (info.functionType()) {
                case QScriptContextInfo::ScriptFunction:
                    functionName = QLatin1String("<anonymous>");
                    break;
                case QScriptContextInfo::NativeFunction:
                    functionName = QLatin1String("<native>");
                    break;
                case QScriptContextInfo::QtFunction:
                case QScriptContextInfo::QtPropertyFunction:
                    functionName = QLatin1String("<native slot>");
                    break;
                }
            } else {
                functionName = QLatin1String("<global>");
            }
        }
        backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), info.lineNumber() ) ) );
    }
    QList<JSAgentWatchData> watches;
    foreach (const QString &expr, watchExpressions)
        watches << JSAgentWatchData::fromScriptValue(expr,  engine()->evaluate(expr));

    QScriptValue activationObject = engine()->currentContext()->activationObject();
    QList<JSAgentWatchData> locals = expandObject(activationObject);

    recordKnownObjects(watches);
    recordKnownObjects(locals);

    // Clear any exceptions occurred during locals evaluation.
    engine()->clearExceptions();

    QByteArray reply;
    QDataStream rs(&reply, QIODevice::WriteOnly);
    rs << QByteArray("STOPPED") << backtrace << watches << locals;
    sendMessage(reply);

    loop.exec(QEventLoop::ExcludeUserInputEvents);
}

void JSDebuggerAgent::continueExec()
{
    loop.quit();
}

void JSDebuggerAgent::enabledChanged(bool on)
{
    engine()->setAgent(on ? this : 0);
    QDeclarativeDebugService::enabledChanged(on);
}

QT_END_NAMESPACE
<commit_msg>QML JS Debugger: Better support of QObject<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtSCriptTools module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** 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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "jsdebuggeragent.h"

#include <QtCore/qcoreapplication.h>
#include <QtCore/qset.h>
#include <QtScript/qscriptengine.h>
#include <QtScript/QScriptContextInfo>
#include <QtCore/QDebug>
#include <QtCore/QUrl>
#include <QtCore/QDateTime>
#include <QtScript/qscriptvalueiterator.h>

QT_BEGIN_NAMESPACE

struct JSAgentWatchData {
    QByteArray exp;
    QString name;
    QString value;
    QString type;
    bool hasChildren;
    quint64 objectId;

    static JSAgentWatchData fromScriptValue(const QString &expression, const QScriptValue &value)
    {
        JSAgentWatchData data;
        data.exp = expression.toUtf8();
        data.name = expression;
        data.hasChildren = false;
        data.value = value.toString();
        data.objectId = value.objectId();
        if (value.isArray()) {
            data.type = QLatin1String("Array");
            data.value = QString::fromLatin1("[Array of length %1]").arg(value.property("length").toString());
            data.hasChildren = true;
        } else if (value.isBool()) {
            data.type = QLatin1String("Bool");
//            data.value = value.toBool() ? QLatin1String("true") : QLatin1String("false");
        } else if (value.isDate()) {
            data.type = QLatin1String("Date");
            data.value = value.toDateTime().toString();
        } else if (value.isError()) {
            data.type = QLatin1String("Error");
        } else if (value.isFunction()) {
            data.type = QLatin1String("Function");
        } else if (value.isUndefined()) {
            data.type = QLatin1String("<undefined>");
        } else if (value.isNumber()) {
            data.type = QLatin1String("Number");
        } else if (value.isRegExp()) {
            data.type = QLatin1String("RegExp");
        } else if (value.isString()) {
            data.type = QLatin1String("String");
        } else if (value.isVariant()) {
            data.type = QLatin1String("Variant");
        } else if (value.isQObject()) {
            const QObject *obj = value.toQObject();
            data.value = QString::fromLatin1("[%1]").arg(obj->metaObject()->className());
            data.type = QLatin1String("Object");
            data.hasChildren = true;
        } else if (value.isObject()) {
            data.type = QLatin1String("Object");
            data.hasChildren = true;
            data.type = QLatin1String("Object");
            data.value = QLatin1String("[Object]");
        } else if (value.isNull()) {
            data.type = QLatin1String("<null>");
        } else {
            data.type = QLatin1String("<unknown>");
        }
        return data;
    }
};

QDataStream& operator<<(QDataStream& s, const JSAgentWatchData& data)
{
    return s << data.exp << data.name << data.value << data.type << data.hasChildren << data.objectId;
}

static QList<JSAgentWatchData> expandObject(const QScriptValue &object)
{
    QList<JSAgentWatchData> result;
    QScriptValueIterator it(object);
    while (it.hasNext()) {
        it.next();
        if (it.flags() & QScriptValue::SkipInEnumeration)
            continue;
        result << JSAgentWatchData::fromScriptValue(it.name(), it.value());
    }
    return result;
}

void JSDebuggerAgent::recordKnownObjects(const QList<JSAgentWatchData>& list)
{
    foreach (const JSAgentWatchData &data, list)
        knownObjectIds << data.objectId;
}

/*!
  Constructs a new agent for the given \a engine. The agent will
  report debugging-related events (e.g. step completion) to the given
  \a backend.
*/
JSDebuggerAgent::JSDebuggerAgent(QScriptEngine *engine)
    : QDeclarativeDebugService("JSDebugger"), QScriptEngineAgent(engine)
{}

/*!
  Destroys this QScriptDebuggerAgent.
*/
JSDebuggerAgent::~JSDebuggerAgent()
{}

/*!
  \reimp
*/
void JSDebuggerAgent::scriptLoad(qint64 id, const QString & program,
                                      const QString &fileName, int )
{
    Q_UNUSED(program);
    filenames.insert(id, QUrl(fileName).toLocalFile());
}

/*!
  \reimp
*/
void JSDebuggerAgent::scriptUnload(qint64 id)
{
    filenames.remove(id);
}

/*!
  \reimp
*/
void JSDebuggerAgent::contextPush()
{
}

/*!
  \reimp
*/
void JSDebuggerAgent::contextPop()
{
}

/*!
  \reimp
*/
void JSDebuggerAgent::functionEntry(qint64 scriptId)
{
    Q_UNUSED(scriptId);
    stepDepth++;
}

/*!
  \reimp
*/
void JSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(returnValue);
    stepDepth--;
}

/*!
  \reimp
*/
void JSDebuggerAgent::positionChange(qint64 scriptId,
                                   int lineNumber, int columnNumber)
{
    Q_UNUSED(columnNumber);

    if(state == Stopped)
        return; //no re-entrency

    // check breakpoints
    if (!breakpointList.isEmpty()) {
        QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
        if (it == filenames.constEnd()) {
            // It is possible that the scripts are loaded before the agent is attached
            QString filename = QUrl(QScriptContextInfo(engine()->currentContext()).fileName()).toLocalFile();
            QPair<QString, qint32> key = qMakePair(filename, lineNumber);
            it = filenames.insert(scriptId, filename);
        }
        QPair<QString, qint32> key = qMakePair(*it, lineNumber);
        if (breakpointList.contains(key)) {
            stopped();
            return;
        }
    }

    switch (state) {
    case NoState:
    case Stopped:
        // Do nothing
        break;

    case SteppingOutState:
        if (stepDepth >= 0)
            break;
        //fallthough
    case SteppingOverState:
        if (stepDepth > 0)
            break;
        //fallthough
    case SteppingIntoState:
        stopped();
        break;
    }

}

/*!
  \reimp
*/
void JSDebuggerAgent::exceptionThrow(qint64 scriptId,
                                   const QScriptValue &exception,
                                   bool hasHandler)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(exception);
    Q_UNUSED(hasHandler);
/* ... */
}

/*!
  \reimp
*/
void JSDebuggerAgent::exceptionCatch(qint64 scriptId,
                                          const QScriptValue &exception)
{
    Q_UNUSED(scriptId);
    Q_UNUSED(exception);
}

void JSDebuggerAgent::messageReceived(const QByteArray& message)
{
    QDataStream ds(message);
    QByteArray command;
    ds >> command;
    if (command == "BREAKPOINTS") {
        ds >> breakpointList;
    } else if (command == "WATCH_EXPRESSIONS") {
        ds >> watchExpressions;
    } else if (command == "STEPOVER") {
        stepDepth = 0;
        state = SteppingOverState;
        continueExec();
    } else if (command == "STEPINTO" || command == "INTERRUPT") {
        stepDepth = 0;
        state = SteppingIntoState;
        continueExec();
    } else if (command == "STEPOUT") {
        stepDepth = 0;
        state = SteppingOutState;
        continueExec();
    } else if (command == "CONTINUE") {
        state = NoState;
        continueExec();
    } else if (command == "EXEC") {
        State oldState = state;
        state = Stopped;
        QByteArray id;
        QString expr;
        ds >> id >> expr;

        JSAgentWatchData data = JSAgentWatchData::fromScriptValue(expr, engine()->evaluate(expr));
        knownObjectIds << data.objectId;
        // Clear any exceptions occurred during locals evaluation.
        engine()->clearExceptions();

        QByteArray reply;
        QDataStream rs(&reply, QIODevice::WriteOnly);
        rs << QByteArray("RESULT") << id << data;
        sendMessage(reply);
        state = oldState;
    } else if (command == "EXPAND") {
        State oldState = state;
        state = Stopped;
        QByteArray requestId;
        quint64 objectId;
        ds >> requestId >> objectId;
        QScriptValue v;
        if (knownObjectIds.contains(objectId))
            v = engine()->objectById(objectId);

        QList<JSAgentWatchData> result = expandObject(v);
        recordKnownObjects(result);

        // Clear any exceptions occurred during locals evaluation.
        engine()->clearExceptions();

        QByteArray reply;
        QDataStream rs(&reply, QIODevice::WriteOnly);
        rs << QByteArray("EXPANDED") << requestId << result;
        sendMessage(reply);
        state = oldState;
    } else if (command == "ACTIVATE_FRAME") {
        State oldState = state;
        state = Stopped;

        int frameId;
        ds >> frameId;

        int deep = 0;
        QScriptContext *ctx = engine()->currentContext();
        while (ctx && deep < frameId) {
            ctx = ctx->parentContext();
            deep++;
        }

        QList<JSAgentWatchData> locals;
        if (ctx)
            locals = expandObject(ctx->activationObject());
        recordKnownObjects(locals);

        // Clear any exceptions occurred during locals evaluation.
        engine()->clearExceptions();

        QByteArray reply;
        QDataStream rs(&reply, QIODevice::WriteOnly);
        rs << QByteArray("LOCALS") << frameId << locals;
        sendMessage(reply);
    } else {
        qDebug() << Q_FUNC_INFO << "Unknown command" << command;
    }

    QDeclarativeDebugService::messageReceived(message);
}

void JSDebuggerAgent::stopped()
{
    knownObjectIds.clear();
    state = Stopped;
    QList<QPair<QString, QPair<QString, qint32> > > backtrace;

    for (QScriptContext* ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) {
        QScriptContextInfo info(ctx);

        QString functionName = info.functionName();
        if (functionName.isEmpty()) {
            if (ctx->parentContext()) {
                switch (info.functionType()) {
                case QScriptContextInfo::ScriptFunction:
                    functionName = QLatin1String("<anonymous>");
                    break;
                case QScriptContextInfo::NativeFunction:
                    functionName = QLatin1String("<native>");
                    break;
                case QScriptContextInfo::QtFunction:
                case QScriptContextInfo::QtPropertyFunction:
                    functionName = QLatin1String("<native slot>");
                    break;
                }
            } else {
                functionName = QLatin1String("<global>");
            }
        }
        backtrace.append(qMakePair(functionName, qMakePair( QUrl(info.fileName()).toLocalFile(), info.lineNumber() ) ) );
    }
    QList<JSAgentWatchData> watches;
    foreach (const QString &expr, watchExpressions)
        watches << JSAgentWatchData::fromScriptValue(expr,  engine()->evaluate(expr));

    QScriptValue activationObject = engine()->currentContext()->activationObject();
    QList<JSAgentWatchData> locals = expandObject(activationObject);

    recordKnownObjects(watches);
    recordKnownObjects(locals);

    // Clear any exceptions occurred during locals evaluation.
    engine()->clearExceptions();

    QByteArray reply;
    QDataStream rs(&reply, QIODevice::WriteOnly);
    rs << QByteArray("STOPPED") << backtrace << watches << locals;
    sendMessage(reply);

    loop.exec(QEventLoop::ExcludeUserInputEvents);
}

void JSDebuggerAgent::continueExec()
{
    loop.quit();
}

void JSDebuggerAgent::enabledChanged(bool on)
{
    engine()->setAgent(on ? this : 0);
    QDeclarativeDebugService::enabledChanged(on);
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/sched_tracker.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/trace_processor.h"

namespace perfetto {
namespace trace_processor {
namespace {

using ::testing::_;
using ::testing::InSequence;
using ::testing::Invoke;

class SchedTrackerTest : public ::testing::Test {
 public:
  SchedTrackerTest() {
    context.storage.reset(new TraceStorage());
    context.process_tracker.reset(new ProcessTracker(&context));
    context.sched_tracker.reset(new SchedTracker(&context));
  }

 protected:
  TraceProcessorContext context;
};

TEST_F(SchedTrackerTest, InsertSecondSched) {
  uint32_t cpu = 3;
  uint64_t timestamp = 100;
  uint32_t pid_1 = 2;
  uint32_t prev_state = 32;
  static const char kCommProc1[] = "process1";
  static const char kCommProc2[] = "process2";
  uint32_t pid_2 = 4;

  const auto& timestamps = context.storage->SlicesForCpu(cpu).start_ns();
  context.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, prev_state,
                                         kCommProc1, pid_2);
  ASSERT_EQ(timestamps.size(), 0);

  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, pid_2, prev_state,
                                         kCommProc2, pid_1);

  ASSERT_EQ(timestamps.size(), 1ul);
  ASSERT_EQ(timestamps[0], timestamp);
  ASSERT_EQ(context.storage->GetThread(1).start_ns, timestamp);
  ASSERT_EQ(std::string(context.storage->GetString(
                context.storage->GetThread(1).name_id)),
            kCommProc2);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).utids().front(), 1);
}

TEST_F(SchedTrackerTest, InsertThirdSched_SameThread) {
  uint32_t cpu = 3;
  uint64_t timestamp = 100;
  uint32_t prev_state = 32;
  static const char kCommProc1[] = "process1";
  static const char kCommProc2[] = "process2";

  const auto& timestamps = context.storage->SlicesForCpu(cpu).start_ns();
  context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, prev_state,
                                         kCommProc1,
                                         /*tid=*/2);
  ASSERT_EQ(timestamps.size(), 0);

  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2,
                                         prev_state, kCommProc1,
                                         /*tid=*/4);
  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4,
                                         prev_state, kCommProc2,
                                         /*tid=*/2);
  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/4,
                                         prev_state, kCommProc1,
                                         /*tid=*/2);

  ASSERT_EQ(timestamps.size(), 3ul);
  ASSERT_EQ(timestamps[0], timestamp);
  ASSERT_EQ(context.storage->GetThread(1).start_ns, timestamp);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).durations().at(0), 1u);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).durations().at(1), 11u - 1u);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).durations().at(2), 31u - 11u);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).utids().at(0),
            context.storage->SlicesForCpu(cpu).utids().at(2));
}

TEST_F(SchedTrackerTest, CounterDuration) {
  uint32_t cpu = 3;
  uint64_t timestamp = 100;
  StringId name_id = 0;
  context.sched_tracker->PushCounter(timestamp, 1000, name_id, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 1, 4000, name_id, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 3, 5000, name_id, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 9, 1000, name_id, cpu,
                                     RefType::kCPU_ID);

  ASSERT_EQ(context.storage->counters().counter_count(), 3ul);
  ASSERT_EQ(context.storage->counters().timestamps().at(0), timestamp);
  ASSERT_EQ(context.storage->counters().durations().at(0), 1);
  ASSERT_EQ(context.storage->counters().values().at(0), 1000);

  ASSERT_EQ(context.storage->counters().timestamps().at(1), timestamp + 1);
  ASSERT_EQ(context.storage->counters().durations().at(1), 2);
  ASSERT_EQ(context.storage->counters().values().at(1), 4000);

  ASSERT_EQ(context.storage->counters().timestamps().at(2), timestamp + 3);
  ASSERT_EQ(context.storage->counters().durations().at(2), 6);
  ASSERT_EQ(context.storage->counters().values().at(2), 5000);
}

TEST_F(SchedTrackerTest, MixedEventsValueDelta) {
  uint32_t cpu = 3;
  uint64_t timestamp = 100;
  StringId name_id_cpu = 0;
  StringId name_id_upid = 0;
  UniquePid upid = 12;
  context.sched_tracker->PushCounter(timestamp, 1000, name_id_cpu, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 1, 0, name_id_upid, upid,
                                     RefType::kUPID);
  context.sched_tracker->PushCounter(timestamp + 3, 5000, name_id_cpu, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 9, 1, name_id_upid, upid,
                                     RefType::kUPID);

  ASSERT_EQ(context.storage->counters().counter_count(), 2ul);
  ASSERT_EQ(context.storage->counters().timestamps().at(0), timestamp);
  ASSERT_EQ(context.storage->counters().durations().at(0), 3);
  ASSERT_EQ(context.storage->counters().values().at(0), 1000);
  ASSERT_EQ(context.storage->counters().value_deltas().at(0), 4000);

  ASSERT_EQ(context.storage->counters().timestamps().at(1), timestamp + 1);
  ASSERT_EQ(context.storage->counters().durations().at(1), 8);
  ASSERT_EQ(context.storage->counters().values().at(1), 0);
  ASSERT_EQ(context.storage->counters().value_deltas().at(1), 1);
}

}  // namespace
}  // namespace trace_processor
}  // namespace perfetto
<commit_msg>trace_processor: Fix sched_tracker_unittest.cc am: f4a7342c6f am: c30394a56c<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/sched_tracker.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/trace_processor.h"

namespace perfetto {
namespace trace_processor {
namespace {

using ::testing::_;
using ::testing::InSequence;
using ::testing::Invoke;

class SchedTrackerTest : public ::testing::Test {
 public:
  SchedTrackerTest() {
    context.storage.reset(new TraceStorage());
    context.process_tracker.reset(new ProcessTracker(&context));
    context.sched_tracker.reset(new SchedTracker(&context));
  }

 protected:
  TraceProcessorContext context;
};

TEST_F(SchedTrackerTest, InsertSecondSched) {
  uint32_t cpu = 3;
  uint64_t timestamp = 100;
  uint32_t pid_1 = 2;
  uint32_t prev_state = 32;
  static const char kCommProc1[] = "process1";
  static const char kCommProc2[] = "process2";
  uint32_t pid_2 = 4;

  const auto& timestamps = context.storage->SlicesForCpu(cpu).start_ns();
  context.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, prev_state,
                                         kCommProc1, pid_2);
  ASSERT_EQ(timestamps.size(), 0);

  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, pid_2, prev_state,
                                         kCommProc2, pid_1);

  ASSERT_EQ(timestamps.size(), 1ul);
  ASSERT_EQ(timestamps[0], timestamp);
  ASSERT_EQ(context.storage->GetThread(1).start_ns, timestamp);
  ASSERT_EQ(std::string(context.storage->GetString(
                context.storage->GetThread(1).name_id)),
            kCommProc2);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).utids().front(), 1);
}

TEST_F(SchedTrackerTest, InsertThirdSched_SameThread) {
  uint32_t cpu = 3;
  uint64_t timestamp = 100;
  uint32_t prev_state = 32;
  static const char kCommProc1[] = "process1";
  static const char kCommProc2[] = "process2";

  const auto& timestamps = context.storage->SlicesForCpu(cpu).start_ns();
  context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, prev_state,
                                         kCommProc1,
                                         /*tid=*/2);
  ASSERT_EQ(timestamps.size(), 0);

  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2,
                                         prev_state, kCommProc1,
                                         /*tid=*/4);
  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4,
                                         prev_state, kCommProc2,
                                         /*tid=*/2);
  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/4,
                                         prev_state, kCommProc1,
                                         /*tid=*/2);

  ASSERT_EQ(timestamps.size(), 3ul);
  ASSERT_EQ(timestamps[0], timestamp);
  ASSERT_EQ(context.storage->GetThread(1).start_ns, timestamp);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).durations().at(0), 1u);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).durations().at(1), 11u - 1u);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).durations().at(2), 31u - 11u);
  ASSERT_EQ(context.storage->SlicesForCpu(cpu).utids().at(0),
            context.storage->SlicesForCpu(cpu).utids().at(2));
}

TEST_F(SchedTrackerTest, CounterDuration) {
  uint32_t cpu = 3;
  uint64_t timestamp = 100;
  StringId name_id = 0;
  context.sched_tracker->PushCounter(timestamp, 1000, name_id, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 1, 4000, name_id, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 3, 5000, name_id, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 9, 1000, name_id, cpu,
                                     RefType::kCPU_ID);

  ASSERT_EQ(context.storage->counters().counter_count(), 3ul);
  ASSERT_EQ(context.storage->counters().timestamps().at(0), timestamp);
  ASSERT_EQ(context.storage->counters().durations().at(0), 1);
  ASSERT_EQ(context.storage->counters().values().at(0), 1000);

  ASSERT_EQ(context.storage->counters().timestamps().at(1), timestamp + 1);
  ASSERT_EQ(context.storage->counters().durations().at(1), 2);
  ASSERT_EQ(context.storage->counters().values().at(1), 4000);

  ASSERT_EQ(context.storage->counters().timestamps().at(2), timestamp + 3);
  ASSERT_EQ(context.storage->counters().durations().at(2), 6);
  ASSERT_EQ(context.storage->counters().values().at(2), 5000);
}

TEST_F(SchedTrackerTest, MixedEventsValueDelta) {
  uint32_t cpu = 3;
  uint64_t timestamp = 100;
  StringId name_id_cpu = 0;
  StringId name_id_upid = 0;
  UniquePid upid = 12;
  context.sched_tracker->PushCounter(timestamp, 1000, name_id_cpu, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 1, 0, name_id_upid, upid,
                                     RefType::kUTID);
  context.sched_tracker->PushCounter(timestamp + 3, 5000, name_id_cpu, cpu,
                                     RefType::kCPU_ID);
  context.sched_tracker->PushCounter(timestamp + 9, 1, name_id_upid, upid,
                                     RefType::kUTID);

  ASSERT_EQ(context.storage->counters().counter_count(), 2ul);
  ASSERT_EQ(context.storage->counters().timestamps().at(0), timestamp);
  ASSERT_EQ(context.storage->counters().durations().at(0), 3);
  ASSERT_EQ(context.storage->counters().values().at(0), 1000);
  ASSERT_EQ(context.storage->counters().value_deltas().at(0), 4000);

  ASSERT_EQ(context.storage->counters().timestamps().at(1), timestamp + 1);
  ASSERT_EQ(context.storage->counters().durations().at(1), 8);
  ASSERT_EQ(context.storage->counters().values().at(1), 0);
  ASSERT_EQ(context.storage->counters().value_deltas().at(1), 1);
}

}  // namespace
}  // namespace trace_processor
}  // namespace perfetto
<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Dario Mangoni, Radu Serban
// =============================================================================

#include "chrono_mkl/ChCSR3Matrix.h"
#include "chrono/core/ChMatrixDynamic.h"

using namespace chrono;

template <class matrix_t>
void PrintMatrix(matrix_t& mat) {
    for (int ii = 0; ii < mat.GetRows(); ii++) {
        for (int jj = 0; jj < mat.GetColumns(); jj++)
            std::cout << mat.GetElement(ii, jj) << "\t";
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

void PrintMatrixCSR(const ChCSR3Matrix& mat) {
    int ncols = mat.GetColumns();
    int nrows = mat.GetRows();
    int* rowindex = mat.GetRowIndexAddress();
    int* colindex = mat.GetColIndexAddress();
    double* values = mat.GetValuesAddress();
    int nnz = rowindex[nrows];

    std::cout << "Num. rows: " << nrows << std::endl;
    std::cout << "Num. cols: " << ncols << std::endl;
    std::cout << "NNZ:       " << nnz << std::endl;
    std::cout << "Row indexes: ";
    for (int i = 0; i <= nrows; i++)
        std::cout << rowindex[i] << "  ";
    std::cout << std::endl;
    std::cout << "Column indexes: ";
    for (int i = 0; i < nnz; i++)
        std::cout << colindex[i] << "  ";
    std::cout << std::endl;
    std::cout << "Values: ";
    for (int i = 0; i < nnz; i++)
        std::cout << values[i] << "  ";
    std::cout << std::endl << std::endl;
}

bool CompareArrays(const ChCSR3Matrix& mat1, const ChCSR3Matrix& mat2, bool only_rowIndex = false) {
    int rows = mat1.GetRows();
    int rows_temp = mat2.GetRows();

    if (rows_temp != rows) {
        std::cout << "Number of rows do not match: ";
        std::cout << "   mat1 -> " << rows;
        std::cout << "   mat2 -> " << rows_temp << std::endl;
        return false;
    }

    for (int cont = 0; cont <= rows; cont++) {
        if (mat1.GetRowIndexAddress()[cont] != mat2.GetRowIndexAddress()[cont]) {
            std::cout << "Row indexes do not match at entry " << cont << ":";
            std::cout << "   mat1 -> " << mat1.GetRowIndexAddress()[cont];
            std::cout << "   mat2 -> " << mat2.GetRowIndexAddress()[cont] << std::endl;
            return false;
        }
    }

    if (only_rowIndex)
        return true;

    for (int cont = 0; cont < mat1.GetRowIndexAddress()[rows]; cont++) {
        if (mat1.GetValuesAddress()[cont] != mat2.GetValuesAddress()[cont]) {
            std::cout << "Values do not match at entry " << cont << ":";
            std::cout << "   mat1 -> " << mat1.GetValuesAddress()[cont];
            std::cout << "   mat2 -> " << mat2.GetValuesAddress()[cont] << std::endl;
            return false;
        }
        if (mat1.GetColIndexAddress()[cont] != mat2.GetColIndexAddress()[cont]) {
            std::cout << "Column indexes do not match at entry " << cont << ":";
            std::cout << "   mat1 -> " << mat1.GetColIndexAddress()[cont];
            std::cout << "   mat2 -> " << mat2.GetColIndexAddress()[cont] << std::endl;
        }
    }

    return true;
}

template <class matrixIN, class matrixOUT>
void FillMatrix(matrixOUT& mat_out, const matrixIN& mat_in) {
    // assert(mat_out.GetRows() == mat_in.GetRows());
    // assert(mat_out.GetColumns() == mat_in.GetColumns());
    for (int m_sel = 0; m_sel < mat_in.GetRows(); m_sel++) {
        for (int n_sel = 0; n_sel < mat_in.GetColumns(); n_sel++) {
            if (mat_in.GetElement(m_sel, n_sel) != 0) {
                ////std::cout << "(" << m_sel << "," << n_sel << ") = " << mat_in.GetElement(m_sel, n_sel) << std::endl;
                mat_out.SetElement(m_sel, n_sel, mat_in.GetElement(m_sel, n_sel));
            }
        }
    }
}

int main() {
    int* nonzeros_vector = nullptr;
    int m = 5;
    int n = 3;

    ChMatrixDynamic<double> mat_base(m, n);
    mat_base(0, 1) = 0.1;
    mat_base(1, 2) = 1.2;
    mat_base(2, 0) = 2.0;
    mat_base(2, 1) = 2.1;
    mat_base(3, 1) = 3.1;
    mat_base(4, 0) = 4.0;
    mat_base(4, 1) = 4.1;

    std::cout << "Base matrix (dense)" << std::endl;
    PrintMatrix(mat_base);

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

    ChCSR3Matrix matCSR3(m, n);
    FillMatrix(matCSR3, mat_base);

    std::cout << "matCSR3" << std::endl;
    PrintMatrix(matCSR3);
    PrintMatrixCSR(matCSR3);

    nonzeros_vector = new int[matCSR3.GetRows()];
    matCSR3.GetNonZerosDistribution(nonzeros_vector);
    std::cout << "NNZ distribution in matCSR3:  " << std::endl;
    for (int i = 0; i < matCSR3.GetRows(); i++)
        std::cout << nonzeros_vector[i] << "  ";
    std::cout << std::endl << std::endl;

    std::cout << "Compare base matrix and matCSR3" << std::endl;
    bool test1 = true;
    for (int m_sel = 0; m_sel < m; m_sel++)
		for (int n_sel = 0; n_sel < n; n_sel++)
			if (mat_base(m_sel, n_sel) != matCSR3.GetElement(m_sel, n_sel))
				test1 = false;
    std::cout << "Test 1: " << (test1 ? "passed" : "NOT passed") << std::endl << std::endl;

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

    ChCSR3Matrix matCSR3_1(m, n, nonzeros_vector);
    FillMatrix(matCSR3_1, mat_base);

    std::cout << "matCSR3_1" << std::endl;
    PrintMatrix(matCSR3_1);
    PrintMatrixCSR(matCSR3_1);

    std::cout << "Compare matCSR3_1 and matCSR3" << std::endl;
    bool test2 = CompareArrays(matCSR3_1, matCSR3);
    std::cout << "Test 2: " << (test2 ? "passed" : "NOT passed") << std::endl << std::endl;

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

    matCSR3_1.Reset(matCSR3_1.GetRows(), matCSR3_1.GetColumns());

    std::cout << "matCSR3_1 after Reset" << std::endl;
    PrintMatrix(matCSR3_1);
    PrintMatrixCSR(matCSR3);

    std::cout << "Compare matCSR3_1 and matCSR3" << std::endl;
    bool test3 = CompareArrays(matCSR3_1, matCSR3, true);
    std::cout << "Test 3: " << (test3 ? "passed" : "NOT passed") << std::endl << std::endl;

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

    delete nonzeros_vector;

    bool passed = test1 && test2 && test3;
    return (!passed);
}<commit_msg>Update unit test for CSR3 matrix<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Dario Mangoni, Radu Serban
// =============================================================================

#include "chrono_mkl/ChCSR3Matrix.h"
#include "chrono/core/ChMatrixDynamic.h"

using namespace chrono;

template <class matrix_t>
void PrintMatrix(matrix_t& mat) {
    for (int ii = 0; ii < mat.GetRows(); ii++) {
        for (int jj = 0; jj < mat.GetColumns(); jj++)
            std::cout << mat.GetElement(ii, jj) << "\t";
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

void PrintMatrixCSR(const ChCSR3Matrix& mat) {
    int ncols = mat.GetColumns();
    int nrows = mat.GetRows();
    int* rowindex = mat.GetRowIndexAddress();
    int* colindex = mat.GetColIndexAddress();
    double* values = mat.GetValuesAddress();
    int nnz = rowindex[nrows];

    std::cout << "Num. rows: " << nrows << std::endl;
    std::cout << "Num. cols: " << ncols << std::endl;
    std::cout << "NNZ:       " << nnz << std::endl;
    std::cout << "Row indexes: ";
    for (int i = 0; i <= nrows; i++)
        std::cout << rowindex[i] << "  ";
    std::cout << std::endl;
    std::cout << "Column indexes: ";
    for (int i = 0; i < nnz; i++)
        std::cout << colindex[i] << "  ";
    std::cout << std::endl;
    std::cout << "Values: ";
    for (int i = 0; i < nnz; i++)
        std::cout << values[i] << "  ";
    std::cout << std::endl << std::endl;
}

bool CompareArrays(const ChCSR3Matrix& mat1, const ChCSR3Matrix& mat2, bool tolerate_uncompressed) {
    int rows = mat1.GetRows();
    int rows_temp = mat2.GetRows();

    if (rows_temp != rows) {
        std::cout << "Number of rows do not match: ";
        std::cout << "   mat1 -> " << rows;
        std::cout << "   mat2 -> " << rows_temp << std::endl;
        return false;
    }

    for (int cont = 0; cont <= rows; cont++) {
        if (mat1.GetRowIndexAddress()[cont] != mat2.GetRowIndexAddress()[cont]) {
            std::cout << "Row indexes do not match at entry " << cont << ":";
            std::cout << "   mat1 -> " << mat1.GetRowIndexAddress()[cont];
            std::cout << "   mat2 -> " << mat2.GetRowIndexAddress()[cont] << std::endl;
            return false;
        }
    }

    for (int cont = 0; cont < mat1.GetRowIndexAddress()[rows]; cont++) {

        if (mat1.GetColIndexAddress()[cont] != mat2.GetColIndexAddress()[cont]) {
            std::cout << "Column indexes do not match at entry " << cont << ":";
            std::cout << "   mat1 -> " << mat1.GetColIndexAddress()[cont];
            std::cout << "   mat2 -> " << mat2.GetColIndexAddress()[cont] << std::endl;
            return false;
        }

        if (mat1.GetColIndexAddress()[cont] != -1 && mat2.GetColIndexAddress()[cont] != -1)
        {
            if (mat1.GetValuesAddress()[cont] != mat2.GetValuesAddress()[cont]) {
                std::cout << "Values do not match at entry " << cont << ":";
                std::cout << "   mat1 -> " << mat1.GetValuesAddress()[cont];
                std::cout << "   mat2 -> " << mat2.GetValuesAddress()[cont] << std::endl;
                return false;
            }
        }
        else
            if (!tolerate_uncompressed)
                return false;

    }

    return true;
}

template <class matrixIN, class matrixOUT>
void FillMatrix(matrixOUT& mat_out, const matrixIN& mat_in) {
    // assert(mat_out.GetRows() == mat_in.GetRows());
    // assert(mat_out.GetColumns() == mat_in.GetColumns());
    for (int m_sel = 0; m_sel < mat_in.GetRows(); m_sel++) {
        for (int n_sel = 0; n_sel < mat_in.GetColumns(); n_sel++) {
            if (mat_in.GetElement(m_sel, n_sel) != 0) {
                ////std::cout << "(" << m_sel << "," << n_sel << ") = " << mat_in.GetElement(m_sel, n_sel) << std::endl;
                mat_out.SetElement(m_sel, n_sel, mat_in.GetElement(m_sel, n_sel));
            }
        }
    }
}

int main() {
    int* nonzeros_vector = nullptr;
    int m = 5;
    int n = 3;

    ChMatrixDynamic<double> ref_matrix(m, n);
    ref_matrix(0, 1) = 0.1;
    ref_matrix(1, 2) = 1.2;
    ref_matrix(2, 0) = 2.0;
    ref_matrix(2, 1) = 2.1;
    ref_matrix(3, 1) = 3.1;
    ref_matrix(4, 0) = 4.0;
    ref_matrix(4, 1) = 4.1;

    std::cout << "Reference matrix (dense)" << std::endl;
    PrintMatrix(ref_matrix);

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

    std::cout << "*********** Test 1: compare dense against CSR3 matrix ***********" << std::endl;
    ChCSR3Matrix matCSR3(m, n);
    FillMatrix(matCSR3, ref_matrix);

    std::cout << "matCSR3" << std::endl;
    PrintMatrix(matCSR3);
    PrintMatrixCSR(matCSR3);

    std::cout << "Compare base matrix and matCSR3" << std::endl;
    bool test1 = true;
    for (int m_sel = 0; m_sel < m; m_sel++)
		for (int n_sel = 0; n_sel < n; n_sel++)
			if (ref_matrix(m_sel, n_sel) != matCSR3.GetElement(m_sel, n_sel))
				test1 = false;
    std::cout << "Test 1: " << (test1 ? "passed" : "NOT passed") << std::endl << std::endl << std::endl;

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

    std::cout << "*********** Test 2: initialization from nonzeros distribution vector ***********" << std::endl;
    nonzeros_vector = new int[matCSR3.GetRows()];
    matCSR3.GetNonZerosDistribution(nonzeros_vector);
    std::cout << "NNZ distribution in matCSR3:  " << std::endl;
    for (int i = 0; i < matCSR3.GetRows(); i++)
        std::cout << nonzeros_vector[i] << "  ";
    std::cout << std::endl;

    ChCSR3Matrix matCSR3_1(m, n, nonzeros_vector);
    delete nonzeros_vector;
    FillMatrix(matCSR3_1, ref_matrix);

    std::cout << "Check matrix builded from nonzeros distribution vector" << std::endl;
    bool test2 = CompareArrays(matCSR3_1, matCSR3, true);
    if (!test2)
    {
        std::cout << "Compare matCSR3 vs matCSR3_1" << std::endl;
        PrintMatrixCSR(matCSR3);
        PrintMatrixCSR(matCSR3_1);
    }
    std::cout << "Test 2: " << (test2 ? "passed" : "NOT passed") << std::endl << std::endl << std::endl;

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

    std::cout << "*********** Test 3: matrix compression invariance **********" << std::endl;
    matCSR3.Compress();
    matCSR3_1.Compress();

    bool test3a = true;
    for (int m_sel = 0; m_sel < m; m_sel++)
        for (int n_sel = 0; n_sel < n; n_sel++)
            if (ref_matrix(m_sel, n_sel) != matCSR3.GetElement(m_sel, n_sel))
                test3a = false;

    std::cout << "Check matrices after compression" << std::endl;
    bool test3b = CompareArrays(matCSR3_1, matCSR3, false);
    if (!test3b)
    {
        std::cout << "Compare matCSR3 vs matCSR3_1" << std::endl;
        PrintMatrixCSR(matCSR3);
        PrintMatrixCSR(matCSR3_1);
    }
    bool test3 = test3a & test3b;
    std::cout << "Test 3: " << (test3 ? "passed" : "NOT passed") << std::endl << std::endl << std::endl;

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

    bool passed = test1 && test2 && test3;
    return !passed;
}<|endoftext|>


<commit_before>/*!
	@file
	@author		Albert Semenov
	@date		11/2007
	@module
*//*
	This file is part of MyGUI.

	MyGUI is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	MyGUI 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 Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "MyGUI_Precompiled.h"
#include "MyGUI_ResourceManager.h"
#include "MyGUI_LayerManager.h"
#include "MyGUI_PointerManager.h"
#include "MyGUI_SkinManager.h"
#include "MyGUI_WidgetManager.h"
#include "MyGUI_XmlDocument.h"
#include "MyGUI_Widget.h"

namespace MyGUI
{

	const std::string XML_TYPE("Pointer");

	MYGUI_INSTANCE_IMPLEMENT(PointerManager);

	void PointerManager::initialise()
	{
		MYGUI_ASSERT(false == mIsInitialise, INSTANCE_TYPE_NAME << " initialised twice");
		MYGUI_LOG(Info, "* Initialise: " << INSTANCE_TYPE_NAME);

		WidgetManager::getInstance().registerUnlinker(this);
		ResourceManager::getInstance().registerLoadXmlDelegate(XML_TYPE) = newDelegate(this, &PointerManager::_load);

		mMousePointer = nullptr;
		mWidgetOwner = nullptr;
		mShow = false;

		MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully initialized");
		mIsInitialise = true;
	}

	void PointerManager::shutdown()
	{
		if (false == mIsInitialise) return;
		MYGUI_LOG(Info, "* Shutdown: " << INSTANCE_TYPE_NAME);

		// удаляем все виджеты
		_destroyAllChildWidget();

		clear();

		WidgetManager::getInstance().unregisterUnlinker(this);
		ResourceManager::getInstance().unregisterLoadXmlDelegate(XML_TYPE);

		MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully shutdown");
		mIsInitialise = false;
	}

	bool PointerManager::load(const std::string & _file, const std::string & _group)
	{
		return ResourceManager::getInstance()._loadImplement(_file, _group, true, XML_TYPE, INSTANCE_TYPE_NAME);
	}

	void PointerManager::_load(xml::ElementPtr _node, const std::string & _file, Version _version)
	{
		std::string layer, def, text;

		// берем детей и крутимся, основной цикл
		xml::ElementEnumerator pointer = _node->getElementEnumerator();
		while (pointer.next(XML_TYPE)) {

			// парсим атрибуты
			pointer->findAttribute("layer", layer);
			pointer->findAttribute("default", def);

			// сохраняем
			text = pointer->findAttribute("texture");

			IntSize textureSize = SkinManager::getTextureSize(text);

			// берем детей и крутимся, основной цикл
			xml::ElementEnumerator info = pointer->getElementEnumerator();
			while (info.next("Info")) {

				std::string name(info->findAttribute("name"));
				if (mMapPointers.find(name) != mMapPointers.end()) {
					MYGUI_LOG(Warning, "pointer '" << name << "' exist, erase old data");
				}

				std::string resource = info->findAttribute("resource");
				IntSize size = IntSize::parse(info->findAttribute("size"));
				IntPoint point = IntPoint::parse(info->findAttribute("point"));

				//новый вариант курсоров
				if ( ! resource.empty() ) {
					ResourceImageSetPtr image = ResourceManager::getInstance().getResource(resource)->castType<ResourceImageSet>();
					mMapPointers[name] = PointerInfo(point, size, image);

				}
				//старый  вариант курсоров
				else {
					// значения параметров
					FloatRect offset(0, 0, 1, 1);

					// парсим атрибуты
					std::string texture(info->findAttribute("texture"));
					std::string offset_str(info->findAttribute("offset"));
					if (false == offset_str.empty()) {
						if (texture.empty()) offset = SkinManager::convertTextureCoord(FloatRect::parse(offset_str), textureSize);
						else offset = SkinManager::convertTextureCoord(FloatRect::parse(offset_str), SkinManager::getTextureSize(texture));
					}

					mMapPointers[name] = PointerInfo(offset, point, size, texture);
				}

			};
		};

		// если есть левел, то пересоеденяем, если нет виджета, то создаем
		if (false == layer.empty()) {
			if (nullptr == mMousePointer) {
				mMousePointer = static_cast<StaticImagePtr>(baseCreateWidget(WidgetStyle::Overlapped, StaticImage::getClassTypeName(), "StaticImage", IntCoord(), Align::Default, "", ""));
			}
			LayerManager::getInstance().attachToLayerKeeper(layer, mMousePointer);
		}

		// если есть дефолтный курсор то меняем
		if (false == def.empty()) mDefaultPointer = def;
		if (false == text.empty()) mTexture = text;

		// если дефолтного нет, то пробуем первый из списка
		if (mDefaultPointer.empty() && !mMapPointers.empty()) mDefaultPointer = mMapPointers.begin()->first;

		// ставим дефолтный указатель
		setPointer(mDefaultPointer, nullptr);
	}

	void PointerManager::clear()
	{
		mWidgetOwner = nullptr;
		mDefaultPointer.clear();
		mTexture.clear();
		mMapPointers.clear();
	}

	void PointerManager::setVisible(bool _visible)
	{
		if (nullptr != mMousePointer) mMousePointer->setVisible(_visible);
		mShow = _visible;
	}

	void PointerManager::setPosition(const IntPoint& _pos)
	{
		if (nullptr != mMousePointer) mMousePointer->setPosition(_pos - mPoint);
	}

	void PointerManager::setPointer(const std::string & _name, WidgetPtr _owner)
	{
		if (nullptr == mMousePointer) return;

		MapPointerInfo::iterator iter = mMapPointers.find(_name);
		if (iter == mMapPointers.end()) return;

		// новый вид курсоров через ресурсы
		if (iter->second.resource != nullptr) {
			if (mMousePointer->getItemResource() != iter->second.resource) {
				mMousePointer->setItemResourceInfo(iter->second.resource->getIndexInfo(0, 0));
			}
		}

		// старый вид курсоров
		else {
			// если курсор имеет свой материал
			if (false == iter->second.texture.empty()) {
				if (mMousePointer->_getTextureName() != iter->second.texture) {
					mMousePointer->_setTextureName(iter->second.texture);
				}
				mMousePointer->deleteAllItems();
				mMousePointer->_setUVSet(iter->second.offset);
			}
			else if (false == mTexture.empty()) {
				if (mMousePointer->_getTextureName() != mTexture) {
					mMousePointer->_setTextureName(mTexture);
				}
				mMousePointer->deleteAllItems();
				mMousePointer->_setUVSet(iter->second.offset);
			}
		}

		// сдвигаем с учетом нового и старого смещения
		mMousePointer->setCoord(
			mMousePointer->getLeft() + mPoint.left - iter->second.point.left,
			mMousePointer->getTop() + mPoint.top - iter->second.point.top,
			iter->second.size.width, iter->second.size.height);

		// и сохраняем новое смещение
		mPoint = iter->second.point;
		mWidgetOwner = _owner;
	}

	void PointerManager::_unlinkWidget(WidgetPtr _widget)
	{
		if (_widget == mWidgetOwner) setPointer(mDefaultPointer, nullptr);
		else if (_widget == mMousePointer) mMousePointer = nullptr;
	}

	// создает виджет
	WidgetPtr PointerManager::baseCreateWidget(WidgetStyle _style, const std::string & _type, const std::string & _skin, const IntCoord& _coord, Align _align, const std::string & _layer, const std::string & _name)
	{
		WidgetPtr widget = WidgetManager::getInstance().createWidget(_style, _type, _skin, _coord, _align, nullptr, nullptr, this, _name);
		mWidgetChild.push_back(widget);
		// присоединяем виджет с уровню
		if (false == _layer.empty()) LayerManager::getInstance().attachToLayerKeeper(_layer, widget);
		return widget;
	}

	// удяляет неудачника
	void PointerManager::_destroyChildWidget(WidgetPtr _widget)
	{
		MYGUI_ASSERT(nullptr != _widget, "invalid widget pointer");

		VectorWidgetPtr::iterator iter = std::find(mWidgetChild.begin(), mWidgetChild.end(), _widget);
		if (iter != mWidgetChild.end()) {

			// сохраняем указатель
			MyGUI::WidgetPtr widget = *iter;

			// удаляем из списка
			*iter = mWidgetChild.back();
			mWidgetChild.pop_back();

			// отписываем от всех
			WidgetManager::getInstance().unlinkFromUnlinkers(_widget);

			// непосредственное удаление
			_deleteWidget(widget);
		}
		else MYGUI_EXCEPT("Widget '" << _widget->getName() << "' not found");
	}

	// удаляет всех детей
	void PointerManager::_destroyAllChildWidget()
	{
		WidgetManager & manager = WidgetManager::getInstance();
		while (false == mWidgetChild.empty()) {

			// сразу себя отписывем, иначе вложенной удаление убивает все
			WidgetPtr widget = mWidgetChild.back();
			mWidgetChild.pop_back();

			// отписываем от всех
			manager.unlinkFromUnlinkers(widget);

			// и сами удалим, так как его больше в списке нет
			_deleteWidget(widget);
		}
	}

} // namespace MyGUI
<commit_msg>fix pointer manager<commit_after>/*!
	@file
	@author		Albert Semenov
	@date		11/2007
	@module
*//*
	This file is part of MyGUI.

	MyGUI is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	MyGUI 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 Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "MyGUI_Precompiled.h"
#include "MyGUI_ResourceManager.h"
#include "MyGUI_LayerManager.h"
#include "MyGUI_PointerManager.h"
#include "MyGUI_SkinManager.h"
#include "MyGUI_WidgetManager.h"
#include "MyGUI_XmlDocument.h"
#include "MyGUI_Widget.h"

namespace MyGUI
{

	const std::string XML_TYPE("Pointer");

	MYGUI_INSTANCE_IMPLEMENT(PointerManager);

	void PointerManager::initialise()
	{
		MYGUI_ASSERT(false == mIsInitialise, INSTANCE_TYPE_NAME << " initialised twice");
		MYGUI_LOG(Info, "* Initialise: " << INSTANCE_TYPE_NAME);

		WidgetManager::getInstance().registerUnlinker(this);
		ResourceManager::getInstance().registerLoadXmlDelegate(XML_TYPE) = newDelegate(this, &PointerManager::_load);

		mMousePointer = nullptr;
		mWidgetOwner = nullptr;
		mShow = false;

		MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully initialized");
		mIsInitialise = true;
	}

	void PointerManager::shutdown()
	{
		if (false == mIsInitialise) return;
		MYGUI_LOG(Info, "* Shutdown: " << INSTANCE_TYPE_NAME);

		// удаляем все виджеты
		_destroyAllChildWidget();

		clear();

		WidgetManager::getInstance().unregisterUnlinker(this);
		ResourceManager::getInstance().unregisterLoadXmlDelegate(XML_TYPE);

		MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully shutdown");
		mIsInitialise = false;
	}

	bool PointerManager::load(const std::string & _file, const std::string & _group)
	{
		return ResourceManager::getInstance()._loadImplement(_file, _group, true, XML_TYPE, INSTANCE_TYPE_NAME);
	}

	void PointerManager::_load(xml::ElementPtr _node, const std::string & _file, Version _version)
	{
		std::string layer, def, text;

		// берем детей и крутимся, основной цикл
		xml::ElementEnumerator pointer = _node->getElementEnumerator();
		while (pointer.next(XML_TYPE)) {

			// парсим атрибуты
			pointer->findAttribute("layer", layer);
			pointer->findAttribute("default", def);

			// сохраняем
			text = pointer->findAttribute("texture");

			IntSize textureSize = SkinManager::getTextureSize(text);

			// берем детей и крутимся, основной цикл
			xml::ElementEnumerator info = pointer->getElementEnumerator();
			while (info.next("Info")) {

				std::string name(info->findAttribute("name"));
				if (mMapPointers.find(name) != mMapPointers.end()) {
					MYGUI_LOG(Warning, "pointer '" << name << "' exist, erase old data");
				}

				std::string resource = info->findAttribute("resource");
				IntSize size = IntSize::parse(info->findAttribute("size"));
				IntPoint point = IntPoint::parse(info->findAttribute("point"));

				//новый вариант курсоров
				if ( ! resource.empty() ) {
					ResourceImageSetPtr image = ResourceManager::getInstance().getResource(resource)->castType<ResourceImageSet>();
					mMapPointers[name] = PointerInfo(point, size, image);

				}
				//старый  вариант курсоров
				else {
					// значения параметров
					FloatRect offset(0, 0, 1, 1);

					// парсим атрибуты
					std::string texture(info->findAttribute("texture"));
					std::string offset_str(info->findAttribute("offset"));
					if (false == offset_str.empty()) {
						if (texture.empty()) offset = SkinManager::convertTextureCoord(FloatRect::parse(offset_str), textureSize);
						else offset = SkinManager::convertTextureCoord(FloatRect::parse(offset_str), SkinManager::getTextureSize(texture));
					}

					mMapPointers[name] = PointerInfo(offset, point, size, texture);
				}

			};
		};

		// если есть левел, то пересоеденяем, если нет виджета, то создаем
		if (false == layer.empty()) {
			if (nullptr == mMousePointer) {
				mMousePointer = static_cast<StaticImagePtr>(baseCreateWidget(WidgetStyle::Overlapped, StaticImage::getClassTypeName(), "StaticImage", IntCoord(), Align::Default, "", ""));
			}
			LayerManager::getInstance().attachToLayerKeeper(layer, mMousePointer);
		}

		// если есть дефолтный курсор то меняем
		if (false == def.empty()) mDefaultPointer = def;
		if (false == text.empty()) mTexture = text;

		// если дефолтного нет, то пробуем первый из списка
		if (mDefaultPointer.empty() && !mMapPointers.empty()) mDefaultPointer = mMapPointers.begin()->first;

		// ставим дефолтный указатель
		setPointer(mDefaultPointer, nullptr);
	}

	void PointerManager::clear()
	{
		mWidgetOwner = nullptr;
		mDefaultPointer.clear();
		mTexture.clear();
		mMapPointers.clear();
	}

	void PointerManager::setVisible(bool _visible)
	{
		if (nullptr != mMousePointer) mMousePointer->setVisible(_visible);
		mShow = _visible;
	}

	void PointerManager::setPosition(const IntPoint& _pos)
	{
		if (nullptr != mMousePointer) mMousePointer->setPosition(_pos - mPoint);
	}

	void PointerManager::setPointer(const std::string & _name, WidgetPtr _owner)
	{
		if (nullptr == mMousePointer) return;

		MapPointerInfo::iterator iter = mMapPointers.find(_name);
		if (iter == mMapPointers.end()) return;

		// новый вид курсоров через ресурсы
		if (iter->second.resource != nullptr) {
			if (mMousePointer->getItemResource() != iter->second.resource) {
				mMousePointer->setItemResourceInfo(iter->second.resource->getIndexInfo(0, 0));
			}
		}

		// старый вид курсоров
		else {
			// если курсор имеет свой материал
			if (false == iter->second.texture.empty()) {
				if (mMousePointer->_getTextureName() != iter->second.texture) {
					mMousePointer->_setTextureName(iter->second.texture);
				}
				mMousePointer->deleteAllItems();
				mMousePointer->_setUVSet(iter->second.offset);
			}
			else if (false == mTexture.empty()) {
				mMousePointer->deleteAllItems();
				mMousePointer->_setUVSet(iter->second.offset);
				if (mMousePointer->_getTextureName() != mTexture) {
					mMousePointer->_setTextureName(mTexture);
				}
			}
		}

		// сдвигаем с учетом нового и старого смещения
		mMousePointer->setCoord(
			mMousePointer->getLeft() + mPoint.left - iter->second.point.left,
			mMousePointer->getTop() + mPoint.top - iter->second.point.top,
			iter->second.size.width, iter->second.size.height);

		// и сохраняем новое смещение
		mPoint = iter->second.point;
		mWidgetOwner = _owner;
	}

	void PointerManager::_unlinkWidget(WidgetPtr _widget)
	{
		if (_widget == mWidgetOwner) setPointer(mDefaultPointer, nullptr);
		else if (_widget == mMousePointer) mMousePointer = nullptr;
	}

	// создает виджет
	WidgetPtr PointerManager::baseCreateWidget(WidgetStyle _style, const std::string & _type, const std::string & _skin, const IntCoord& _coord, Align _align, const std::string & _layer, const std::string & _name)
	{
		WidgetPtr widget = WidgetManager::getInstance().createWidget(_style, _type, _skin, _coord, _align, nullptr, nullptr, this, _name);
		mWidgetChild.push_back(widget);
		// присоединяем виджет с уровню
		if (false == _layer.empty()) LayerManager::getInstance().attachToLayerKeeper(_layer, widget);
		return widget;
	}

	// удяляет неудачника
	void PointerManager::_destroyChildWidget(WidgetPtr _widget)
	{
		MYGUI_ASSERT(nullptr != _widget, "invalid widget pointer");

		VectorWidgetPtr::iterator iter = std::find(mWidgetChild.begin(), mWidgetChild.end(), _widget);
		if (iter != mWidgetChild.end()) {

			// сохраняем указатель
			MyGUI::WidgetPtr widget = *iter;

			// удаляем из списка
			*iter = mWidgetChild.back();
			mWidgetChild.pop_back();

			// отписываем от всех
			WidgetManager::getInstance().unlinkFromUnlinkers(_widget);

			// непосредственное удаление
			_deleteWidget(widget);
		}
		else MYGUI_EXCEPT("Widget '" << _widget->getName() << "' not found");
	}

	// удаляет всех детей
	void PointerManager::_destroyAllChildWidget()
	{
		WidgetManager & manager = WidgetManager::getInstance();
		while (false == mWidgetChild.empty()) {

			// сразу себя отписывем, иначе вложенной удаление убивает все
			WidgetPtr widget = mWidgetChild.back();
			mWidgetChild.pop_back();

			// отписываем от всех
			manager.unlinkFromUnlinkers(widget);

			// и сами удалим, так как его больше в списке нет
			_deleteWidget(widget);
		}
	}

} // namespace MyGUI
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------
//    @FileName         :    NFPluginLoader.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :
//    @Module           :    NFPluginLoader
//
// -------------------------------------------------------------------------

//#include <crtdbg.h>
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>
#include "NFCActorManager.h"
#include "NFComm/Config/NFConfig.h"
#include "NFComm/NFPluginModule/NFPlatform.h"

#if NF_PLATFORM == NF_PLATFORM_LINUX
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#endif

#if NF_PLATFORM == NF_PLATFORM_WIN

#pragma comment( lib, "DbgHelp" )
// Dumpļ
void CreateDumpFile(const std::string& strDumpFilePathName, EXCEPTION_POINTERS* pException)
{
    // Dumpļ
    HANDLE hDumpFile = CreateFile(strDumpFilePathName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // DumpϢ
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // дDumpļ
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);
}

// Unhandled ExceptionĻص
long ApplicationCrashHandler(EXCEPTION_POINTERS* pException)
{
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf_s(szDmupName, "%04d_%02d_%02d_%02d_%02d_%02d.dmp",  ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    CreateDumpFile(szDmupName, pException);

    FatalAppExit(-1,  szDmupName);

    return EXCEPTION_EXECUTE_HANDLER;
}
#endif

void CloseXButton()
{
#if NF_PLATFORM == NF_PLATFORM_WIN

    HWND hWnd = GetConsoleWindow();
    if (hWnd)
    {
        HMENU hMenu = GetSystemMenu(hWnd, FALSE);
        EnableMenuItem(hMenu, SC_CLOSE, MF_DISABLED | MF_BYCOMMAND);
    }

#endif
}

bool bExitApp = false;
std::thread gThread;

void ThreadFunc()
{
    while (!bExitApp)
    {
        //std::this_thread::sleep_for(std::chrono::milliseconds(1000));

        //         std::string s;
        //         std::cin >> s;
        //         if ( 0 == stricmp( s.c_str(), "exit" ) )
        //         {
        //             bExitApp = true;
        //         }
    }
}

void CreateBackThread()
{
    //gThread = std::thread(std::bind(&ThreadFunc));
    //auto f = std::async (std::launch::async, std::bind(ThreadFunc));
    //std::cout << "CreateBackThread, thread ID = " << gThread.get_id() << std::endl;
}

void InitDaemon()
{
#if NF_PLATFORM == NF_PLATFORM_LINUX
    daemon(1, 0);

    // ignore signals
    signal(SIGINT,  SIG_IGN);
    signal(SIGHUP,  SIG_IGN);
    signal(SIGQUIT, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGTTOU, SIG_IGN);
    signal(SIGTTIN, SIG_IGN);
    signal(SIGTERM, SIG_IGN);
#endif
}

void PrintfLogo()
{
#if NF_PLATFORM == NF_PLATFORM_WIN
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif

    std::cout << "\n" << std::endl;
    std::cout << "" << std::endl;
    std::cout << "                                            " << std::endl;
    std::cout << "                 NoahFrame                  " << std::endl;
    std::cout << "   Copyright (c) 2011-2016  NFrame Studio   " << std::endl;
    std::cout << "             All rights reserved.           " << std::endl;
    std::cout << "                                            " << std::endl;
    std::cout << "" << std::endl;
    std::cout << "\n" << std::endl;

#if NF_PLATFORM == NF_PLATFORM_WIN
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif // NF_PLATFORM
}

#if NF_PLATFORM == NF_PLATFORM_WIN || NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_APPLE
int main(int argc, char* argv[])
#elif  NF_PLATFORM == NF_PLATFORM_ANDROID || NF_PLATFORM == NF_PLATFORM_APPLE_IOS

#endif
{
#if NF_PLATFORM == NF_PLATFORM_WIN
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
#elif NF_PLATFORM == NF_PLATFORM_LINUX
    bool bDaemon = false;

    if (argc > 1)
    {
        if (0 == NFSTRICMP((const char*)argv[1], "-d"))
        {
            bDaemon = true;
        }
    }

    if (bDaemon)
    {
        InitDaemon();
    }

    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);

#endif
    NFCActorManager::GetSingletonPtr()->Init();
    NFCActorManager::GetSingletonPtr()->AfterInit();
    NFCActorManager::GetSingletonPtr()->CheckConfig();

    PrintfLogo();

    CloseXButton();
    CreateBackThread();

    while (!bExitApp)    //DEBUG汾RELEASE
    {
        while (true)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1));

            if (bExitApp)
            {
                break;
            }

#if NF_PLATFORM == NF_PLATFORM_WIN
            __try
            {
#endif
                NFCActorManager::GetSingletonPtr()->Execute();
#if NF_PLATFORM == NF_PLATFORM_WIN
            }
            __except (ApplicationCrashHandler(GetExceptionInformation()))
            {
            }
#endif
        }
    }

    NFCActorManager::GetSingletonPtr()->BeforeShut();
    NFCActorManager::GetSingletonPtr()->Shut();

    NFCActorManager::GetSingletonPtr()->ReleaseInstance();

    return 0;
}
<commit_msg>show the x button when it run in debug mode<commit_after>// -------------------------------------------------------------------------
//    @FileName         :    NFPluginLoader.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :
//    @Module           :    NFPluginLoader
//
// -------------------------------------------------------------------------

//#include <crtdbg.h>
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>
#include "NFCActorManager.h"
#include "NFComm/Config/NFConfig.h"
#include "NFComm/NFPluginModule/NFPlatform.h"

#if NF_PLATFORM == NF_PLATFORM_LINUX
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#endif

#if NF_PLATFORM == NF_PLATFORM_WIN

#pragma comment( lib, "DbgHelp" )
// Dumpļ
void CreateDumpFile(const std::string& strDumpFilePathName, EXCEPTION_POINTERS* pException)
{
    // Dumpļ
    HANDLE hDumpFile = CreateFile(strDumpFilePathName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // DumpϢ
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // дDumpļ
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);
}

// Unhandled ExceptionĻص
long ApplicationCrashHandler(EXCEPTION_POINTERS* pException)
{
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf_s(szDmupName, "%04d_%02d_%02d_%02d_%02d_%02d.dmp",  ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    CreateDumpFile(szDmupName, pException);

    FatalAppExit(-1,  szDmupName);

    return EXCEPTION_EXECUTE_HANDLER;
}
#endif

void CloseXButton()
{
#if defined(NF_DEBUG_MODE)
#if NF_PLATFORM == NF_PLATFORM_WIN
	HWND hWnd = GetConsoleWindow();
	if (hWnd)
	{
		HMENU hMenu = GetSystemMenu(hWnd, FALSE);
		EnableMenuItem(hMenu, SC_CLOSE, MF_DISABLED | MF_BYCOMMAND);
	}
#endif
#endif
}

bool bExitApp = false;
std::thread gThread;

void ThreadFunc()
{
    while (!bExitApp)
    {
        //std::this_thread::sleep_for(std::chrono::milliseconds(1000));

        //         std::string s;
        //         std::cin >> s;
        //         if ( 0 == stricmp( s.c_str(), "exit" ) )
        //         {
        //             bExitApp = true;
        //         }
    }
}

void CreateBackThread()
{
    //gThread = std::thread(std::bind(&ThreadFunc));
    //auto f = std::async (std::launch::async, std::bind(ThreadFunc));
    //std::cout << "CreateBackThread, thread ID = " << gThread.get_id() << std::endl;
}

void InitDaemon()
{
#if NF_PLATFORM == NF_PLATFORM_LINUX
    daemon(1, 0);

    // ignore signals
    signal(SIGINT,  SIG_IGN);
    signal(SIGHUP,  SIG_IGN);
    signal(SIGQUIT, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGTTOU, SIG_IGN);
    signal(SIGTTIN, SIG_IGN);
    signal(SIGTERM, SIG_IGN);
#endif
}

void PrintfLogo()
{
#if NF_PLATFORM == NF_PLATFORM_WIN
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif

    std::cout << "\n" << std::endl;
    std::cout << "" << std::endl;
    std::cout << "                                            " << std::endl;
    std::cout << "                 NoahFrame                  " << std::endl;
    std::cout << "   Copyright (c) 2011-2016  NFrame Studio   " << std::endl;
    std::cout << "             All rights reserved.           " << std::endl;
    std::cout << "                                            " << std::endl;
    std::cout << "" << std::endl;
    std::cout << "\n" << std::endl;

#if NF_PLATFORM == NF_PLATFORM_WIN
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif // NF_PLATFORM
}

#if NF_PLATFORM == NF_PLATFORM_WIN || NF_PLATFORM == NF_PLATFORM_LINUX || NF_PLATFORM == NF_PLATFORM_APPLE
int main(int argc, char* argv[])
#elif  NF_PLATFORM == NF_PLATFORM_ANDROID || NF_PLATFORM == NF_PLATFORM_APPLE_IOS

#endif
{
#if NF_PLATFORM == NF_PLATFORM_WIN
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
#elif NF_PLATFORM == NF_PLATFORM_LINUX
    bool bDaemon = false;

    if (argc > 1)
    {
        if (0 == NFSTRICMP((const char*)argv[1], "-d"))
        {
            bDaemon = true;
        }
    }

    if (bDaemon)
    {
        InitDaemon();
    }

    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);

#endif
    NFCActorManager::GetSingletonPtr()->Init();
    NFCActorManager::GetSingletonPtr()->AfterInit();
    NFCActorManager::GetSingletonPtr()->CheckConfig();

    PrintfLogo();

    CloseXButton();
    CreateBackThread();

    while (!bExitApp)    //DEBUG汾RELEASE
    {
        while (true)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1));

            if (bExitApp)
            {
                break;
            }

#if NF_PLATFORM == NF_PLATFORM_WIN
            __try
            {
#endif
                NFCActorManager::GetSingletonPtr()->Execute();
#if NF_PLATFORM == NF_PLATFORM_WIN
            }
            __except (ApplicationCrashHandler(GetExceptionInformation()))
            {
            }
#endif
        }
    }

    NFCActorManager::GetSingletonPtr()->BeforeShut();
    NFCActorManager::GetSingletonPtr()->Shut();

    NFCActorManager::GetSingletonPtr()->ReleaseInstance();

    return 0;
}
<|endoftext|>


<commit_before>#include "gb_cairo_box_gradient.h"
#include <utils/gb_utils_save_buffer.h>
#include <utils/gb_utils_timer.h>
#include <gb_settings.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>

#include <fstream>
#include <iostream>

using std::ifstream;
using std::ios_base;
using std::cout;
using std::cin;
using std::endl;

void GBCairoBoxGradientBenchmark::init()
{
    benchmark_name = "Cairo box gradient";
    benchmark_file_name = "gb_cairo_box_gradient.png";
    return;
}

void GBCairoBoxGradientBenchmark::render()
{
    // todo: parametrise
    cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1920, 1200);
    cairo_t *cr = cairo_create (surface);
    int counter;

    GBTimer timer;

    // TODO: parametrise
    cairo_set_line_width (cr, 1);
    cairo_set_antialias(cr, CAIRO_ANTIALIAS_SUBPIXEL);
    cairo_set_source_rgba(cr, 0.5, 0.5, 1, 0.5);

    cairo_pattern_t *gradient = cairo_pattern_create_linear(0, 0, 100, 100);
    cairo_pattern_add_color_stop_rgba(gradient, 0, 0, 0, 1, 0.5);
    cairo_pattern_add_color_stop_rgba(gradient, 0, 0, 1, 0, 0.5);
    cairo_set_source(cr, gradient);

    timer.start();
    for (counter=0; counter < app_state.metadata->num_elements; counter++)
    {
        Box box = app_state.drawdata->boxes[counter];
        cairo_rectangle(cr, box.x, box.y, box.width, box.height);
        cairo_fill (cr);
    }
    timer.stop();

    print_timing(timer);

    if (GB_SAVE_BENCHMARK_IMAGE)
    {
        gb_save_buffer(benchmark_file_name, cairo_image_surface_get_data(surface), GB_CANVAS_WIDTH, GB_CANVAS_HEIGHT, GB_CANVAS_BPP, GB_CANVAS_CAIRO_FORMAT);
    }

    cairo_pattern_destroy(gradient);
    cairo_destroy (cr);
    cairo_surface_destroy (surface);
    return;
}

<commit_msg>Fix for cairo box gradient example.<commit_after>#include "gb_cairo_box_gradient.h"
#include <utils/gb_utils_save_buffer.h>
#include <utils/gb_utils_timer.h>
#include <gb_settings.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>

#include <fstream>
#include <iostream>

using std::ifstream;
using std::ios_base;
using std::cout;
using std::cin;
using std::endl;

void GBCairoBoxGradientBenchmark::init()
{
    benchmark_name = "Cairo box gradient";
    benchmark_file_name = "gb_cairo_box_gradient.png";
    return;
}

void GBCairoBoxGradientBenchmark::render()
{
    // todo: parametrise
    cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1920, 1200);
    cairo_t *cr = cairo_create (surface);
    int counter;

    GBTimer timer;

    // TODO: parametrise
    cairo_set_line_width (cr, 1);
    cairo_set_antialias(cr, CAIRO_ANTIALIAS_SUBPIXEL);
    cairo_set_source_rgba(cr, 0.5, 0.5, 1, 0.5);

    timer.start();
    for (counter=0; counter < app_state.metadata->num_elements; counter++)
    {
        Box box = app_state.drawdata->boxes[counter];

        cairo_pattern_t *gradient = cairo_pattern_create_linear(box.x, box.y, box.x + box.width, box.y + box.height);
        cairo_pattern_add_color_stop_rgba(gradient, 0, 0, 0, 1, 0.5);
        cairo_pattern_add_color_stop_rgba(gradient, 0.5, 1, 1, 0, 0.5);
        cairo_pattern_add_color_stop_rgba(gradient, 1, 1, 0, 0, 0.5);
        cairo_set_source(cr, gradient);
        cairo_rectangle(cr, box.x, box.y, box.width, box.height);
        cairo_fill (cr);
        cairo_pattern_destroy(gradient);
    }
    timer.stop();

    print_timing(timer);

    if (GB_SAVE_BENCHMARK_IMAGE)
    {
        gb_save_buffer( benchmark_file_name, cairo_image_surface_get_data(surface),
                        GB_CANVAS_WIDTH, GB_CANVAS_HEIGHT, GB_CANVAS_BPP, GB_CANVAS_CAIRO_FORMAT);
    }

    cairo_destroy (cr);
    cairo_surface_destroy (surface);
    return;
}

<|endoftext|>