<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qtest.h>
#include <QLibraryInfo>
#include <QDir>
#include <QProcess>
#include <QDebug>
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQmlError>

static QtMsgHandler testlibMsgHandler = 0;
void msgHandlerFilter(QtMsgType type, const char *msg)
{
    if (type == QtCriticalMsg || type == QtFatalMsg)
        (*testlibMsgHandler)(type, msg);
}

class tst_examples : public QObject
{
    Q_OBJECT
public:
    tst_examples();

private slots:
    void init();
    void cleanup();

    void sgexamples_data();
    void sgexamples();
    void sgsnippets_data();
    void sgsnippets();

    void namingConvention();
private:
    QStringList excludedDirs;
    QStringList excludedFiles;

    void namingConvention(const QDir &);
    QStringList findQmlFiles(const QDir &);

    QQmlEngine engine;
};

tst_examples::tst_examples()
{
    // Add files to exclude here
    excludedFiles << "doc/src/snippets/qml/listmodel.qml"; //Just a ListModel, no root QQuickItem

    // Add directories you want excluded here (don't add examples/, because they install to examples/qtdeclarative/)
    excludedDirs << "shared"; //Not an example
    excludedDirs << "qtquick/text/fonts"; // QTBUG-21415
    excludedDirs << "doc/src/snippets/qml/path"; //No root QQuickItem
    excludedDirs << "tutorials/gettingStartedQml"; //C++ example, but no cpp files in root dir

    // These snippets are not expected to run on their own.
    excludedDirs << "doc/src/snippets/qml/visualdatamodel_rootindex";
    excludedDirs << "doc/src/snippets/qml/qtbinding";
    excludedDirs << "doc/src/snippets/qml/imports";

#ifdef QT_NO_WEBKIT
    excludedDirs << "qtquick/modelviews/webview";
    excludedDirs << "demos/webbrowser";
    excludedDirs << "doc/src/snippets/qml/webview";
#endif

#ifdef QT_NO_XMLPATTERNS
    excludedDirs << "demos/twitter";
    excludedDirs << "demos/flickr";
    excludedDirs << "demos/photoviewer";
#endif
}

void tst_examples::init()
{
    if (!qstrcmp(QTest::currentTestFunction(), "sgsnippets"))
        testlibMsgHandler = qInstallMsgHandler(msgHandlerFilter);
}

void tst_examples::cleanup()
{
    if (!qstrcmp(QTest::currentTestFunction(), "sgsnippets"))
        qInstallMsgHandler(testlibMsgHandler);
}

/*
This tests that the examples follow the naming convention required
to have them tested by the examples() test.
*/
void tst_examples::namingConvention(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return;
    }

    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                    QDir::Files);

    bool seenQml = !files.isEmpty();
    bool seenLowercase = false;

    foreach (const QString &file, files) {
        if (file.at(0).isLower())
            seenLowercase = true;
    }

    if (!seenQml) {
        QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                QDir::NoSymLinks);
        foreach (const QString &dir, dirs) {
            QDir sub = d;
            sub.cd(dir);
            namingConvention(sub);
        }
    } else if(!seenLowercase) {
        QFAIL(qPrintable(QString(
            "Directory %1 violates naming convention; expected at least one qml file "
            "starting with lower case, got: %2"
        ).arg(d.absolutePath()).arg(files.join(","))));
    }
}

void tst_examples::namingConvention()
{
    QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);

    namingConvention(QDir(examples));
}

QStringList tst_examples::findQmlFiles(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return QStringList();
    }

    QStringList rv;

    QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
    if (cppfiles.isEmpty()) {
        QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                        QDir::Files);
        foreach (const QString &file, files) {
            if (file.at(0).isLower()) {
                bool superContinue = false;
                for (int ii = 0; ii < excludedFiles.count(); ++ii) {
                    QString e = excludedFiles.at(ii);
                    if (d.absoluteFilePath(file).endsWith(e)) {
                        superContinue = true;
                        break;
                    }
                }
                if (superContinue)
                    continue;
                rv << d.absoluteFilePath(file);
            }
        }
    }

    QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                                   QDir::NoSymLinks);
    foreach (const QString &dir, dirs) {
        QDir sub = d;
        sub.cd(dir);
        rv << findQmlFiles(sub);
    }

    return rv;
}

/*
This test runs all the examples in the QtQml UI source tree and ensures
that they start and exit cleanly.

Examples are any .qml files under the examples/ directory that start
with a lower case letter.
*/
void tst_examples::sgexamples_data()
{
    QTest::addColumn<QString>("file");

    QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";

    QStringList files;
    files << findQmlFiles(QDir(examples));

    foreach (const QString &file, files)
        QTest::newRow(qPrintable(file)) << file;
}

void tst_examples::sgexamples()
{
    QFETCH(QString, file);

#if defined(QTEST_CROSS_COMPILED)
    QSKIP("sources not available when cross compiled");
#endif

    QQmlComponent component(&engine, QUrl::fromLocalFile(file));
    if (component.status() == QQmlComponent::Error)
        qWarning() << component.errors();
    QCOMPARE(component.status(), QQmlComponent::Ready);

    QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
    QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
    if (!root)
        component.completeCreate();
    QVERIFY(root);

    QQuickCanvas canvas;
    root->setParentItem(canvas.rootItem());
    component.completeCreate();
    canvas.show();

    QTest::qWaitForWindowShown(&canvas);

}

void tst_examples::sgsnippets_data()
{
    QTest::addColumn<QString>("file");

    QString snippets = QLatin1String(SRCDIR) + "/../../../../doc/src/snippets/qml";

    QStringList files;
    files << findQmlFiles(QDir(snippets));

    foreach (const QString &file, files)
        QTest::newRow(qPrintable(file)) << file;
}

void tst_examples::sgsnippets()
{
    QFETCH(QString, file);

#if defined(QTEST_CROSS_COMPILED)
    QSKIP("sources not available when cross compiled");
#endif

    QQmlComponent component(&engine, QUrl::fromLocalFile(file));
    if (component.status() == QQmlComponent::Error)
        qWarning() << component.errors();
    QCOMPARE(component.status(), QQmlComponent::Ready);

    QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
    QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
    if (!root)
        component.completeCreate();
    QVERIFY(root);

    QQuickCanvas canvas;
    root->setParentItem(canvas.rootItem());
    component.completeCreate();
    canvas.show();

    QTest::qWaitForWindowShown(&canvas);

}

QTEST_MAIN(tst_examples)

#include "tst_examples.moc"
<commit_msg>Reuse a QQuickCanvas in examples auto test.<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qtest.h>
#include <QLibraryInfo>
#include <QDir>
#include <QProcess>
#include <QDebug>
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQmlError>

static QtMsgHandler testlibMsgHandler = 0;
void msgHandlerFilter(QtMsgType type, const char *msg)
{
    if (type == QtCriticalMsg || type == QtFatalMsg)
        (*testlibMsgHandler)(type, msg);
}

class tst_examples : public QObject
{
    Q_OBJECT
public:
    tst_examples();
    ~tst_examples();

private slots:
    void init();
    void cleanup();

    void sgexamples_data();
    void sgexamples();
    void sgsnippets_data();
    void sgsnippets();

    void namingConvention();
private:
    QStringList excludedDirs;
    QStringList excludedFiles;

    void namingConvention(const QDir &);
    QStringList findQmlFiles(const QDir &);

    QQmlEngine engine;

    QQuickCanvas *canvas;
};

tst_examples::tst_examples() : canvas(0)
{
    // Add files to exclude here
    excludedFiles << "doc/src/snippets/qml/listmodel.qml"; //Just a ListModel, no root QQuickItem

    // Add directories you want excluded here (don't add examples/, because they install to examples/qtdeclarative/)
    excludedDirs << "shared"; //Not an example
    excludedDirs << "qtquick/text/fonts"; // QTBUG-21415
    excludedDirs << "doc/src/snippets/qml/path"; //No root QQuickItem
    excludedDirs << "tutorials/gettingStartedQml"; //C++ example, but no cpp files in root dir

    // These snippets are not expected to run on their own.
    excludedDirs << "doc/src/snippets/qml/visualdatamodel_rootindex";
    excludedDirs << "doc/src/snippets/qml/qtbinding";
    excludedDirs << "doc/src/snippets/qml/imports";

#ifdef QT_NO_WEBKIT
    excludedDirs << "qtquick/modelviews/webview";
    excludedDirs << "demos/webbrowser";
    excludedDirs << "doc/src/snippets/qml/webview";
#endif

#ifdef QT_NO_XMLPATTERNS
    excludedDirs << "demos/twitter";
    excludedDirs << "demos/flickr";
    excludedDirs << "demos/photoviewer";
#endif
}

tst_examples::~tst_examples()
{
    delete canvas;
}

void tst_examples::init()
{
    if (!qstrcmp(QTest::currentTestFunction(), "sgsnippets"))
        testlibMsgHandler = qInstallMsgHandler(msgHandlerFilter);
}

void tst_examples::cleanup()
{
    if (!qstrcmp(QTest::currentTestFunction(), "sgsnippets"))
        qInstallMsgHandler(testlibMsgHandler);
}

/*
This tests that the examples follow the naming convention required
to have them tested by the examples() test.
*/
void tst_examples::namingConvention(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return;
    }

    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                    QDir::Files);

    bool seenQml = !files.isEmpty();
    bool seenLowercase = false;

    foreach (const QString &file, files) {
        if (file.at(0).isLower())
            seenLowercase = true;
    }

    if (!seenQml) {
        QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                QDir::NoSymLinks);
        foreach (const QString &dir, dirs) {
            QDir sub = d;
            sub.cd(dir);
            namingConvention(sub);
        }
    } else if(!seenLowercase) {
        QFAIL(qPrintable(QString(
            "Directory %1 violates naming convention; expected at least one qml file "
            "starting with lower case, got: %2"
        ).arg(d.absolutePath()).arg(files.join(","))));
    }
}

void tst_examples::namingConvention()
{
    QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);

    namingConvention(QDir(examples));
}

QStringList tst_examples::findQmlFiles(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return QStringList();
    }

    QStringList rv;

    QStringList cppfiles = d.entryList(QStringList() << QLatin1String("*.cpp"), QDir::Files);
    if (cppfiles.isEmpty()) {
        QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                        QDir::Files);
        foreach (const QString &file, files) {
            if (file.at(0).isLower()) {
                bool superContinue = false;
                for (int ii = 0; ii < excludedFiles.count(); ++ii) {
                    QString e = excludedFiles.at(ii);
                    if (d.absoluteFilePath(file).endsWith(e)) {
                        superContinue = true;
                        break;
                    }
                }
                if (superContinue)
                    continue;
                rv << d.absoluteFilePath(file);
            }
        }
    }

    QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                                   QDir::NoSymLinks);
    foreach (const QString &dir, dirs) {
        QDir sub = d;
        sub.cd(dir);
        rv << findQmlFiles(sub);
    }

    return rv;
}

/*
This test runs all the examples in the QtQml UI source tree and ensures
that they start and exit cleanly.

Examples are any .qml files under the examples/ directory that start
with a lower case letter.
*/
void tst_examples::sgexamples_data()
{
    QTest::addColumn<QString>("file");

    QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";

    QStringList files;
    files << findQmlFiles(QDir(examples));

    foreach (const QString &file, files)
        QTest::newRow(qPrintable(file)) << file;
}

void tst_examples::sgexamples()
{
    QFETCH(QString, file);

#if defined(QTEST_CROSS_COMPILED)
    QSKIP("sources not available when cross compiled");
#endif

    QQmlComponent component(&engine, QUrl::fromLocalFile(file));
    if (component.status() == QQmlComponent::Error)
        qWarning() << component.errors();
    QCOMPARE(component.status(), QQmlComponent::Ready);

    QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
    QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
    if (!root)
        component.completeCreate();
    QVERIFY(root);

    if (!canvas) {
        canvas = new QQuickCanvas();
        canvas->resize(240, 320);
        canvas->show();
        QTest::qWaitForWindowShown(canvas);
    }
    root->setParentItem(canvas->rootItem());
    component.completeCreate();

    qApp->processEvents();
}

void tst_examples::sgsnippets_data()
{
    QTest::addColumn<QString>("file");

    QString snippets = QLatin1String(SRCDIR) + "/../../../../doc/src/snippets/qml";

    QStringList files;
    files << findQmlFiles(QDir(snippets));

    foreach (const QString &file, files)
        QTest::newRow(qPrintable(file)) << file;
}

void tst_examples::sgsnippets()
{
    QFETCH(QString, file);

#if defined(QTEST_CROSS_COMPILED)
    QSKIP("sources not available when cross compiled");
#endif

    QQmlComponent component(&engine, QUrl::fromLocalFile(file));
    if (component.status() == QQmlComponent::Error)
        qWarning() << component.errors();
    QCOMPARE(component.status(), QQmlComponent::Ready);

    QScopedPointer<QObject> object(component.beginCreate(engine.rootContext()));
    QQuickItem *root = qobject_cast<QQuickItem *>(object.data());
    if (!root)
        component.completeCreate();
    QVERIFY(root);

    if (!canvas) {
        canvas = new QQuickCanvas();
        canvas->resize(240, 320);
        canvas->show();
        QTest::qWaitForWindowShown(canvas);
    }
    root->setParentItem(canvas->rootItem());
    component.completeCreate();

    qApp->processEvents();
}

QTEST_MAIN(tst_examples)

#include "tst_examples.moc"
<|endoftext|>


<commit_before>/*
 * Node.cpp
 *
 *  Created on: 2016-02-13
 *      Author: derek
 */

#include "Node.h"
#include "Move.h"
#include "GameBoard.h"
#include "Heuristic.h"
#include <queue>
#include <memory>
#include <limits>
#include <cstdint>
#include <cassert>
using namespace std;

Node::Node(std::unique_ptr<GameBoard> state, Node* const parent,
		std::unique_ptr<Move> action, uint8_t depth,
		Heuristic alpha, Heuristic beta, bool maximizer)
	: state{std::move(state)},
	  parent{parent},
	  action{std::move(action)},
	  depth{depth},
	  alpha{alpha},
	  beta{beta},
	  maximizer{maximizer},
	  bestChildValue{maximizer ? Heuristic::min() : Heuristic::max()},
	  nextNodeMove{0, 0},
	  bestChild{nullptr}
{
	// If they called it with a null GameBoard,
	// they probably want a blank game state
	if (state == nullptr)
	{
		state.reset(new GameBoard);
	}
}

// For a root node
Node::Node(unique_ptr<GameBoard> state, uint8_t depth, bool maximizer)
	: Node(std::move(state), nullptr, nullptr, depth, Heuristic::min(),
			Heuristic::max(), maximizer)
{
}

// We will expand child nodes until we have explored all possible moves,
// or beta > alpha. Note that beta is our strongest lower bound and alpha
// is our strongest upper bound, so beta > alpha indicates a game state that
// any sane opponent will never let happen.
//
// We also stop expanding nodes when depth reaches 0 or when the game is over.
bool Node::hasNextNode() const
{
	return depth > 0 && !isTerminalState() &&
			get<0>(nextNodeMove) <= 2 && get<1>(nextNodeMove) <= 2
			&& beta > alpha;
}

void Node::expandNextNode(queue<Node>& fringe)
{
	for (auto x = get<0>(nextNodeMove); x < 3; ++x)
	{
		for (auto y = get<1>(nextNodeMove); y < 3; ++y)
		{
			if (state->get(x, y) == ' ')
			{
				// Add child state to the fringe
				auto newBoard = unique_ptr<GameBoard>{new GameBoard{*state}};
				auto newMove = unique_ptr<Move>{new Move{x, y}};
				newBoard->makeMove(*newMove);
				fringe.emplace(Node{std::move(newBoard), this, std::move(newMove),
					depth > 0 ? depth - 1 : 0, alpha, beta, !maximizer});

				// Increment the next move coordinates
				if (x < 2)
				{
					nextNodeMove = decltype(nextNodeMove){ x + 1, y };
				}
				else if (y < 2)
				{
					nextNodeMove = decltype(nextNodeMove){ 0, y + 1 };
				}
				else
				{
					// Invalid move
					nextNodeMove = decltype(nextNodeMove){ 3, 3 };
				}

				return; // Should only expand one node at a time
			}
		}
	}
}

Heuristic Node::getValue() const
{
	if ((parent && (depth == 0)) || isTerminalState())
	{
		return parent->state->getHeuristic(*action);
	}
	else if (maximizer)
	{
		return beta;
	}
	else
	{
		return alpha;
	}
}

void Node::updateParent()
{
	if (parent)
	{
		parent->update(*this);
	}
}

void Node::update(const Node& child)
{
	if (maximizer)
	{
		if (child.getValue() > bestChildValue)
		{
			bestChildValue = child.getValue();
			bestChild = &child;
			alpha = std::max(alpha, bestChildValue);
		}
	}
	else
	{
		if (child.getValue() < bestChildValue)
		{
			bestChildValue = child.getValue();
			bestChild = &child;
			beta = std::min(beta, bestChildValue);
		}
	}
}

bool Node::isTerminalState() const
{
	return state->endState() != ttt::EndState::NotOver;
}

Move Node::getBestMove() const
{
	assert(bestChild != nullptr);
	return *bestChild->action;
}
<commit_msg>Fixed bug where move iteration skipped squares<commit_after>/*
 * Node.cpp
 *
 *  Created on: 2016-02-13
 *      Author: derek
 */

#include "Node.h"
#include "Move.h"
#include "GameBoard.h"
#include "Heuristic.h"
#include <queue>
#include <memory>
#include <limits>
#include <cstdint>
#include <cassert>
using namespace std;

Node::Node(std::unique_ptr<GameBoard> state, Node* const parent,
		std::unique_ptr<Move> action, uint8_t depth,
		Heuristic alpha, Heuristic beta, bool maximizer)
	: state{std::move(state)},
	  parent{parent},
	  action{std::move(action)},
	  depth{depth},
	  alpha{alpha},
	  beta{beta},
	  maximizer{maximizer},
	  bestChildValue{maximizer ? Heuristic::min() : Heuristic::max()},
	  nextNodeMove{0, 0},
	  bestChild{nullptr}
{
	// If they called it with a null GameBoard,
	// they probably want a blank game state
	if (state == nullptr)
	{
		state.reset(new GameBoard);
	}
}

// For a root node
Node::Node(unique_ptr<GameBoard> state, uint8_t depth, bool maximizer)
	: Node(std::move(state), nullptr, nullptr, depth, Heuristic::min(),
			Heuristic::max(), maximizer)
{
}

// We will expand child nodes until we have explored all possible moves,
// or beta > alpha. Note that beta is our strongest lower bound and alpha
// is our strongest upper bound, so beta > alpha indicates a game state that
// any sane opponent will never let happen.
//
// We also stop expanding nodes when depth reaches 0 or when the game is over.
bool Node::hasNextNode() const
{
	return depth > 0 && !isTerminalState() &&
			get<0>(nextNodeMove) <= 2 && get<1>(nextNodeMove) <= 2
			&& beta > alpha;
}

void Node::expandNextNode(queue<Node>& fringe)
{
	// Use the stored x on the first loop, but every loop after that it should
	// reset to 0 when we go to a new row.
	auto x = get<0>(nextNodeMove);

	for (auto y = get<1>(nextNodeMove); y < 3; ++y)
	{
		for (/* first init x as stored value, then 0 */ ; x < 3; ++x)
		{
			if (state->get(x, y) == ' ')
			{
				// Add child state to the fringe
				auto newBoard = unique_ptr<GameBoard>{new GameBoard{*state}};
				auto newMove = unique_ptr<Move>{new Move{x, y}};
				newBoard->makeMove(*newMove);
				fringe.emplace(Node{std::move(newBoard), this,
					std::move(newMove), depth > 0 ? depth - 1 : 0,
					alpha, beta, !maximizer});

				// Increment the next move coordinates
				if (x < 2)
				{
					nextNodeMove = decltype(nextNodeMove){ x + 1, y };
				}
				else if (y < 2)
				{
					nextNodeMove = decltype(nextNodeMove){ 0, y + 1 };
				}
				else
				{
					// Invalid move indicates no more moves remaining
					nextNodeMove = decltype(nextNodeMove){ 3, 3 };
				}

				return; // Should only expand one node at a time
			}
		}
		x = 0; // On a new row, so reset x to 0
	}
}

Heuristic Node::getValue() const
{
	if ((parent && (depth == 0)) || isTerminalState())
	{
		return parent->state->getHeuristic(*action);
	}
	else if (maximizer)
	{
		return beta;
	}
	else
	{
		return alpha;
	}
}

void Node::updateParent()
{
	if (parent)
	{
		parent->update(*this);
	}
}

void Node::update(const Node& child)
{
	if (maximizer)
	{
		if (child.getValue() > bestChildValue)
		{
			bestChildValue = child.getValue();
			bestChild = &child;
			alpha = std::max(alpha, bestChildValue);
		}
	}
	else
	{
		if (child.getValue() < bestChildValue)
		{
			bestChildValue = child.getValue();
			bestChild = &child;
			beta = std::min(beta, bestChildValue);
		}
	}
}

bool Node::isTerminalState() const
{
	return state->endState() != ttt::EndState::NotOver;
}

Move Node::getBestMove() const
{
	assert(bestChild != nullptr);
	return *bestChild->action;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#ifdef HAVE_CVS_IDENT
#ident "$Id: PData.cc,v 1.1 2003/01/26 21:15:58 steve Exp $"
#endif

# include  "PData.h"

PData::PData(const hname_t&h)
: hname_(h)
{
}

PData::~PData()
{
}

const hname_t&PData::name() const
{
      return hname_;
}

/*
 * $Log: PData.cc,v $
 * Revision 1.1  2003/01/26 21:15:58  steve
 *  Rework expression parsing and elaboration to
 *  accommodate real/realtime values and expressions.
 *
 */

<commit_msg> missing include of config.h<commit_after>/*
 * Copyright (c) 2003 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#ifdef HAVE_CVS_IDENT
#ident "$Id: PData.cc,v 1.2 2003/11/10 20:11:01 steve Exp $"
#endif

# include  "config.h"
# include  "PData.h"

PData::PData(const hname_t&h)
: hname_(h)
{
}

PData::~PData()
{
}

const hname_t&PData::name() const
{
      return hname_;
}

/*
 * $Log: PData.cc,v $
 * Revision 1.2  2003/11/10 20:11:01  steve
 *  missing include of config.h
 *
 * Revision 1.1  2003/01/26 21:15:58  steve
 *  Rework expression parsing and elaboration to
 *  accommodate real/realtime values and expressions.
 *
 */

<|endoftext|>


<commit_before>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  Gearmand client and server library.
 *
 *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *      * Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *      * Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following disclaimer
 *  in the documentation and/or other materials provided with the
 *  distribution.
 *
 *      * The names of its contributors may not be used to endorse or
 *  promote products derived from this software without specific prior
 *  written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <config.h>
#include <libtest/test.hpp>

using namespace libtest;

#include <cassert>
#include <cstring>
#include <libgearman/gearman.h>
#include <string>
#include <tests/execute.h>

#ifndef __INTEL_COMPILER
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif

test_return_t gearman_execute_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  test_true(client);
  const char *worker_function= (const char *)gearman_client_context(client);
  test_true(worker_function);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));

  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, NULL, &value, 0), gearman_client_error(client));
  test_compare(test_literal_param_size("test load"), gearman_result_size(gearman_task_result(task)));
  test_false(gearman_task_is_known(task));
  test_false(gearman_task_is_running(task));

  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_NULL_workload_TEST(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  test_true(client);
  const char *worker_function= (const char *)gearman_client_context(client);
  test_true(worker_function);

  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));

  gearman_task_attr_t task_attr= gearman_task_attr_init_background(GEARMAN_JOB_PRIORITY_NORMAL);

  gearman_task_st *task;
  test_true(task= gearman_execute(client,
                                  test_string_make_from_cstr(worker_function),
                                  NULL, 0, // unique
                                  &task_attr, // gearman_task_attr_t
                                  NULL, // argument
                                  0));
  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_NULL_attr_NULL_workload_TEST(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  test_true(client);
  const char *worker_function= (const char *)gearman_client_context(client);
  test_true(worker_function);

  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));

  gearman_task_st *task;
  test_true(task= gearman_execute(client,
                                  test_string_make_from_cstr(worker_function),
                                  NULL, 0, // unique
                                  NULL, // gearman_task_attr_t
                                  NULL, // argument
                                  0));
  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_fail_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("fail"));

  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, NULL, &value, 0), gearman_client_error(client));
  test_compare_got(GEARMAN_WORK_FAIL, gearman_task_return(task), gearman_task_error(task));
  test_false(gearman_task_is_known(task));
  test_false(gearman_task_is_running(task));

  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_timeout_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);
  test_truth(client);

  gearman_client_set_timeout(client, 4);

  // We should fail since the the timeout is small and the function should
  // not exist.
  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, NULL, &value, 0), gearman_client_error(client));
  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_epoch_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  gearman_task_attr_t task_attr= gearman_task_attr_init_epoch(time(NULL) +5, GEARMAN_JOB_PRIORITY_NORMAL);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function),
                                      NULL, 0, // unique
                                      &task_attr, &value, 0), gearman_client_error(client));
  test_truth(task);
  test_truth(gearman_task_job_handle(task));
  test_true(gearman_task_is_known(task));
  test_false(gearman_task_is_running(task));
  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_epoch_check_job_handle_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  gearman_task_attr_t task_attr= gearman_task_attr_init_epoch(time(NULL) +5, GEARMAN_JOB_PRIORITY_NORMAL);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, &task_attr, &value, 0), gearman_client_error(client));

  test_truth(task);
  test_truth(gearman_task_job_handle(task));

  gearman_return_t rc;
  bool is_known;
  do {
    rc= gearman_client_job_status(client, gearman_task_job_handle(task), &is_known, NULL, NULL, NULL);
  }  while (gearman_continue(rc) or is_known);
  test_compare(GEARMAN_SUCCESS, rc);

  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_bg_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  gearman_task_attr_t task_attr= gearman_task_attr_init_background(GEARMAN_JOB_PRIORITY_NORMAL);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), test_literal_param("my id"), &task_attr, &value, 0),
                gearman_client_error(client));

  // Lets make sure we have a task
  test_truth(task);
  test_truth(gearman_task_job_handle(task));

  test_true_got(gearman_success(gearman_client_run_tasks(client)), gearman_client_error(client));

  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_multile_bg_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  for (uint32_t x= 0; x < 4; /* No reason for number */ x++)
  {
    gearman_task_attr_t task_attr= gearman_task_attr_init_background(GEARMAN_JOB_PRIORITY_NORMAL);

    gearman_task_st *task;
    gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
    test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, &task_attr, &value, 0),
                  gearman_client_error(client));

    // Lets make sure we have a task
    test_truth(task);
    test_truth(gearman_task_job_handle(task));
  }

  test_compare(GEARMAN_SUCCESS,
               gearman_client_run_tasks(client));

  gearman_client_task_free_all(client);

  return TEST_SUCCESS;
}
<commit_msg>REmove unused variable.<commit_after>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  Gearmand client and server library.
 *
 *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *      * Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *      * Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following disclaimer
 *  in the documentation and/or other materials provided with the
 *  distribution.
 *
 *      * The names of its contributors may not be used to endorse or
 *  promote products derived from this software without specific prior
 *  written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <config.h>
#include <libtest/test.hpp>

using namespace libtest;

#include <cassert>
#include <cstring>
#include <libgearman/gearman.h>
#include <string>
#include <tests/execute.h>

#ifndef __INTEL_COMPILER
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif

test_return_t gearman_execute_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  test_true(client);
  const char *worker_function= (const char *)gearman_client_context(client);
  test_true(worker_function);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));

  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, NULL, &value, 0), gearman_client_error(client));
  test_compare(test_literal_param_size("test load"), gearman_result_size(gearman_task_result(task)));
  test_false(gearman_task_is_known(task));
  test_false(gearman_task_is_running(task));

  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_NULL_workload_TEST(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  test_true(client);
  const char *worker_function= (const char *)gearman_client_context(client);
  test_true(worker_function);

  gearman_task_attr_t task_attr= gearman_task_attr_init_background(GEARMAN_JOB_PRIORITY_NORMAL);

  gearman_task_st *task;
  test_true(task= gearman_execute(client,
                                  test_string_make_from_cstr(worker_function),
                                  NULL, 0, // unique
                                  &task_attr, // gearman_task_attr_t
                                  NULL, // argument
                                  0));
  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_NULL_attr_NULL_workload_TEST(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  test_true(client);
  const char *worker_function= (const char *)gearman_client_context(client);
  test_true(worker_function);

  gearman_task_st *task;
  test_true(task= gearman_execute(client,
                                  test_string_make_from_cstr(worker_function),
                                  NULL, 0, // unique
                                  NULL, // gearman_task_attr_t
                                  NULL, // argument
                                  0));
  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_fail_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("fail"));

  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, NULL, &value, 0), gearman_client_error(client));
  test_compare_got(GEARMAN_WORK_FAIL, gearman_task_return(task), gearman_task_error(task));
  test_false(gearman_task_is_known(task));
  test_false(gearman_task_is_running(task));

  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_timeout_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);
  test_truth(client);

  gearman_client_set_timeout(client, 4);

  // We should fail since the the timeout is small and the function should
  // not exist.
  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, NULL, &value, 0), gearman_client_error(client));
  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_epoch_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  gearman_task_attr_t task_attr= gearman_task_attr_init_epoch(time(NULL) +5, GEARMAN_JOB_PRIORITY_NORMAL);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function),
                                      NULL, 0, // unique
                                      &task_attr, &value, 0), gearman_client_error(client));
  test_truth(task);
  test_truth(gearman_task_job_handle(task));
  test_true(gearman_task_is_known(task));
  test_false(gearman_task_is_running(task));
  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_epoch_check_job_handle_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  gearman_task_attr_t task_attr= gearman_task_attr_init_epoch(time(NULL) +5, GEARMAN_JOB_PRIORITY_NORMAL);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, &task_attr, &value, 0), gearman_client_error(client));

  test_truth(task);
  test_truth(gearman_task_job_handle(task));

  gearman_return_t rc;
  bool is_known;
  do {
    rc= gearman_client_job_status(client, gearman_task_job_handle(task), &is_known, NULL, NULL, NULL);
  }  while (gearman_continue(rc) or is_known);
  test_compare(GEARMAN_SUCCESS, rc);

  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_bg_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  gearman_task_attr_t task_attr= gearman_task_attr_init_background(GEARMAN_JOB_PRIORITY_NORMAL);

  gearman_task_st *task;
  gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
  test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), test_literal_param("my id"), &task_attr, &value, 0),
                gearman_client_error(client));

  // Lets make sure we have a task
  test_truth(task);
  test_truth(gearman_task_job_handle(task));

  test_true_got(gearman_success(gearman_client_run_tasks(client)), gearman_client_error(client));

  gearman_task_free(task);

  return TEST_SUCCESS;
}

test_return_t gearman_execute_multile_bg_test(void *object)
{
  gearman_client_st *client= (gearman_client_st *)object;
  const char *worker_function= (const char *)gearman_client_context(client);
  assert(worker_function);

  for (uint32_t x= 0; x < 4; /* No reason for number */ x++)
  {
    gearman_task_attr_t task_attr= gearman_task_attr_init_background(GEARMAN_JOB_PRIORITY_NORMAL);

    gearman_task_st *task;
    gearman_argument_t value= gearman_argument_make(0, 0, test_literal_param("test load"));
    test_true_got(task= gearman_execute(client, test_string_make_from_cstr(worker_function), NULL, 0, &task_attr, &value, 0),
                  gearman_client_error(client));

    // Lets make sure we have a task
    test_truth(task);
    test_truth(gearman_task_job_handle(task));
  }

  test_compare(GEARMAN_SUCCESS,
               gearman_client_run_tasks(client));

  gearman_client_task_free_all(client);

  return TEST_SUCCESS;
}
<|endoftext|>


<commit_before>#include "include/catch.hpp"
#include "common.hpp"
#include "RTC/NackGenerator.hpp"
#include "RTC/RtpPacket.hpp"
#include <vector>

using namespace RTC;

struct Input
{
	Input() = default;
	Input(uint16_t seq, uint16_t firstNacked, size_t numNacked)
		: seq(seq), firstNacked(firstNacked), numNacked(numNacked)
		{}

	uint16_t seq{ 0 };
	uint16_t firstNacked{ 0 };
	size_t numNacked{ 0 };
} currentInput;

class TestNackGeneratorListener : public NackGenerator::Listener
{
	void OnNackGeneratorNackRequired(const std::vector<uint16_t>& seqNumbers) override
	{
		auto it = seqNumbers.begin();
		auto firstNacked = *it;

		auto numNacked = seqNumbers.size();

		REQUIRE(currentInput.firstNacked == firstNacked);
		REQUIRE(currentInput.numNacked == numNacked);
	};

	void OnNackGeneratorKeyFrameRequired() override
	{
	}
};

uint8_t rtpBuffer[] =
{
	0b10000000, 0b01111011, 0b01010010, 0b00001110,
	0b01011011, 0b01101011, 0b11001010, 0b10110101,
	0, 0, 0, 2
};

// [pt:123, seq:21006, timestamp:1533790901]
RtpPacket* packet = RtpPacket::Parse(rtpBuffer, sizeof(rtpBuffer));

void validate(std::vector<Input>& inputs)
{
	TestNackGeneratorListener* listener = new TestNackGeneratorListener();
	NackGenerator* nackGenerator = new NackGenerator(listener);

	for (auto input : inputs)
	{
		currentInput = input;
		packet->SetSequenceNumber(input.seq);
		nackGenerator->ReceivePacket(packet);
	}
};

SCENARIO("NACK generator", "[rtp][rtcp]")
{
	SECTION("ignore too old packets")
	{
		std::vector<Input> inputs =
		{
			{ 2371, 0, 0 },
			{ 2372, 0, 0 },
			{ 2373, 0, 0 },
			{ 2374, 0, 0 },
			{ 2375, 0, 0 },
			{ 2376, 0, 0 },
			{ 2377, 0, 0 },
			{ 2378, 0, 0 },
			{ 2379, 0, 0 },
			{ 2380, 0, 0 },
			{ 2254, 0, 0 },
			{ 2250, 0, 0 },
		};

		validate(inputs);
	}

	SECTION("generate NACK for missing ordered packet")
	{
		std::vector<Input> inputs =
		{
			{ 2381, 0, 0 },
			{ 2383, 2382, 1 }
		};

		validate(inputs);
	}

	SECTION("sequence wrap generates no NACK")
	{
		std::vector<Input> inputs =
		{
			{ 65534, 0, 0 },
			{ 65535, 0, 0 },
			{     0, 0, 0 }
		};

		validate(inputs);
	}

	SECTION("generate NACK after sequence wrap")
	{
		std::vector<Input> inputs =
		{
			{ 65534, 0, 0 },
			{ 65535, 0, 0 },
			{     1, 0, 1 }
		};

		validate(inputs);
	}

	SECTION("generate NACK after sequence wrap, and yet another NACK")
	{
		std::vector<Input> inputs =
		{
			{ 65534, 0, 0 },
			{ 65535, 0, 0 },
			{     1, 0, 1 },
			{    11, 2, 9 }
		};

		validate(inputs);
	}
}
<commit_msg>NackGenerator: tests. Add more tests<commit_after>#include "include/catch.hpp"
#include "common.hpp"
#include "RTC/NackGenerator.hpp"
#include "RTC/RtpPacket.hpp"
#include <vector>

using namespace RTC;

struct Input
{
	Input() = default;
	Input(uint16_t seq, uint16_t firstNacked, size_t numNacked)
		: seq(seq), firstNacked(firstNacked), numNacked(numNacked)
		{}

	uint16_t seq{ 0 };
	uint16_t firstNacked{ 0 };
	size_t numNacked{ 0 };
} currentInput;

class TestNackGeneratorListener : public NackGenerator::Listener
{
	void OnNackGeneratorNackRequired(const std::vector<uint16_t>& seqNumbers) override
	{
		auto it = seqNumbers.begin();
		auto firstNacked = *it;

		auto numNacked = seqNumbers.size();

		REQUIRE(currentInput.firstNacked == firstNacked);
		REQUIRE(currentInput.numNacked == numNacked);
	};

	void OnNackGeneratorKeyFrameRequired() override
	{
	}
};

uint8_t rtpBuffer[] =
{
	0b10000000, 0b01111011, 0b01010010, 0b00001110,
	0b01011011, 0b01101011, 0b11001010, 0b10110101,
	0, 0, 0, 2
};

// [pt:123, seq:21006, timestamp:1533790901]
RtpPacket* packet = RtpPacket::Parse(rtpBuffer, sizeof(rtpBuffer));

void validate(std::vector<Input>& inputs)
{
	TestNackGeneratorListener* listener = new TestNackGeneratorListener();
	NackGenerator* nackGenerator = new NackGenerator(listener);

	for (auto input : inputs)
	{
		currentInput = input;
		packet->SetSequenceNumber(input.seq);
		nackGenerator->ReceivePacket(packet);
	}
};

SCENARIO("NACK generator", "[rtp][rtcp]")
{
	SECTION("ignore too old packets")
	{
		std::vector<Input> inputs =
		{
			{ 2371, 0, 0 },
			{ 2372, 0, 0 },
			{ 2373, 0, 0 },
			{ 2374, 0, 0 },
			{ 2375, 0, 0 },
			{ 2376, 0, 0 },
			{ 2377, 0, 0 },
			{ 2378, 0, 0 },
			{ 2379, 0, 0 },
			{ 2380, 0, 0 },
			{ 2254, 0, 0 },
			{ 2250, 0, 0 },
		};

		validate(inputs);
	}

	SECTION("generate NACK for missing ordered packet")
	{
		std::vector<Input> inputs =
		{
			{ 2381, 0, 0 },
			{ 2383, 2382, 1 }
		};

		validate(inputs);
	}

	SECTION("sequence wrap generates no NACK")
	{
		std::vector<Input> inputs =
		{
			{ 65534, 0, 0 },
			{ 65535, 0, 0 },
			{     0, 0, 0 }
		};

		validate(inputs);
	}

	SECTION("generate NACK after sequence wrap")
	{
		std::vector<Input> inputs =
		{
			{ 65534, 0, 0 },
			{ 65535, 0, 0 },
			{     1, 0, 1 }
		};

		validate(inputs);
	}

	SECTION("generate NACK after sequence wrap, and yet another NACK")
	{
		std::vector<Input> inputs =
		{
			{ 65534, 0, 0 },
			{ 65535, 0, 0 },
			{     1, 0, 1 },
			{    11, 2, 9 }
		};

		validate(inputs);
	}

	SECTION("intercalated missing packets")
	{
		std::vector<Input> inputs =
		{
			{ 1, 0, 0 },
			{ 3, 2, 1 },
			{ 5, 4, 1 },
			{ 7, 6, 1 },
			{ 9, 8, 1 }
		};

		validate(inputs);
	}

	SECTION("non contiguous intercalated missing packets")
	{
		std::vector<Input> inputs =
		{
			{ 1, 0, 0 },
			{ 3, 2, 1 },
			{ 7, 4, 3 },
			{ 9, 8, 1 }
		};

		validate(inputs);
	}

	SECTION("big jump")
	{
		std::vector<Input> inputs =
		{
			{   1, 0,   0 },
			{ 300, 2, 298 },
			{   3, 0,   0 },
			{   4, 0,   0 },
			{   5, 0,   0 }
		};

		validate(inputs);
	}

	SECTION("big jump. Nack list too large to be requested")
	{
		std::vector<Input> inputs =
		{
			{    1, 0, 0 },
			{ 3000, 0, 0 }
		};

		validate(inputs);
	}
}
<|endoftext|>


<commit_before>/****************************************************************************************[ReTime.C]
Copyright (c) 2008, Niklas Sorensson

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.
**************************************************************************************************/

#include "circ/DagShrink.h"
#include "circ/ReTime.h"

using namespace Minisat;

//=================================================================================================
// Helpers:

static inline void removeDeadFlops(Circ& c, Box& b, Flops& flp)
{
    vec<Gate> xs;
    GSet      reached_gates;

    // Calculate all gates reachable from some (real) output:
    //
    for (int i = 0; i < b.outs.size(); i++)
        xs.push(gate(b.outs[i]));

    while (xs.size() > 0){
        Gate g = xs.last(); xs.pop();

        if (reached_gates.has(g))
            continue;
        reached_gates.insert(g);

        assert(g != gate_Undef);
        if (type(g) == gtype_And){
            xs.push(gate(c.lchild(g)));
            xs.push(gate(c.rchild(g)));
        }else if (type(g) == gtype_Inp && flp.isFlop(g))
            xs.push(gate(flp.def(g)));
    }

    int gates_before = c.nGates();
    int flops_before = flp.size();
    int inps_before  = b.inps.size();
    int outs_before  = b.outs.size();
    // Create reduced flop set:
    //
    Flops tmp_flops; tmp_flops.adjust(c);
    for (int i = 0; i < flp.size(); i++)
        if (reached_gates.has(flp[i]))
            tmp_flops.defineFlop(flp[i], flp.def(flp[i]));
        // else
        //     printf(" >> FLOP x%d not reached\n", index(flp[i]));
    tmp_flops.moveTo(flp);

    // for (int i = 0; i < flp.size(); i++){
    //     printf("CHECKING FLOP: %d, def = %d\n", index(flp[i]), index(gate(flp.def(flp[i]))));
    //     assert(flp.def(flp[i]) != sig_Undef);
    // }
    assert(inps_before == b.inps.size());
    assert(outs_before == b.outs.size());

    // Remove now dead logic:
    removeDeadLogic(c, b, flp);

    fprintf(stderr, " >>> REMOVE DEAD FLOPS (before: gates=%d, flops=%d) (after: gates=%d, flops=%d, outs = %d)\n",
            gates_before, flops_before, c.nGates(), flp.size(), outs_before);
}

static inline bool retimeable(const Circ& from, const Flops& from_flp, Gate g)
{
    assert(type(g) == gtype_And);

    Gate x = gate(from.lchild(g));
    Gate y = gate(from.rchild(g));

    return type(x) == gtype_Inp && from_flp.isFlop(x)
        && type(y) == gtype_Inp && from_flp.isFlop(y)
        // && (from.nFanouts(x) == 1 || from.nFanouts(y) == 1);
         && from.nFanouts(x) == 1 && from.nFanouts(y) == 1;
}

static inline bool hasInput(const Circ& from, Gate g, const GMap<Sig>& map)
{
    assert(type(g) == gtype_And);

    Gate x = gate(from.lchild(g));
    Gate y = gate(from.rchild(g));

    return map[x] != sig_Undef && map[y] != sig_Undef;
}

static inline bool tryReTime(const Circ& from, const Flops& from_flp, Circ& to, Flops& new_flops, Gate g, GMap<Sig>& map)
{
    assert(type(g) == gtype_And);
    assert(type(from.lchild(g)) == gtype_Inp && from_flp.isFlop(gate(from.lchild(g))));
    assert(type(from.rchild(g)) == gtype_Inp && from_flp.isFlop(gate(from.rchild(g))));

    bool init_val = sign(from.lchild(g)) && sign(from.rchild(g));
    Sig  x_from   = from_flp.def(gate(from.lchild(g))) ^ sign(from.lchild(g));
    Sig  y_from   = from_flp.def(gate(from.rchild(g))) ^ sign(from.rchild(g));

         if (map[gate(x_from)] == sig_Undef) return false;
    else if (map[gate(y_from)] == sig_Undef) return false;

    Sig  x_to     = map[gate(x_from)] ^ sign(x_from);
    Sig  y_to     = map[gate(y_from)] ^ sign(y_from);

    // {
    //     Sig x = from.lchild(g);
    //     Sig y = from.rchild(g);
    //
    //     printf("retiming gate %d:\n", index(g));
    //     printf("...lchild: %s%d\n", sign(x)?"-":"", index(gate(x)));
    //     printf("...rchild: %s%d\n", sign(y)?"-":"", index(gate(y)));
    //     printf("...x_from: %s%d\\%d\n", sign(x_from)?"-":"", index(gate(x_from)), from.nFanouts(gate(x)));
    //     printf("...y_from: %s%d\\%d\n", sign(y_from)?"-":"", index(gate(y_from)), from.nFanouts(gate(y)));
    //     printf("...x_to  : %s%d\n", sign(x_to)?"-":"", index(gate(x_to)));
    //     printf("...y_to  : %s%d\n", sign(y_to)?"-":"", index(gate(y_to)));
    // }

    Sig  next_sig = to.mkAnd(x_to, y_to);
    Gate new_flop = gate(to.mkInp());
    map[g]        = mkSig(new_flop, init_val);

    new_flops.adjust(to);
    new_flops.defineFlop(new_flop, next_sig ^ init_val);

    return true;
}

static inline void mergeEqualFlops(Circ& c, Box& b, Flops& flp)
{
    Circ      to;
    GMap<Sig> map;
    map.growTo(c.lastGate(), sig_Undef);

    // Copy inputs (including flop gates):
    for (int i = 0; i < b.inps.size(); i++) map[b.inps[i]] = to.mkInp();
    for (int i = 0; i < flp.size(); i++)    map[flp[i]]    = to.mkInp();

    vec<Gate> keep_flops;
    for (int i = 0; i < flp.size(); i++){
        for (int j = 0; j < i; j++)
            if (flp.def(flp[j]) == flp.def(flp[i])){
                map[flp[i]] = map[flp[j]];
                printf(" EQUAL FLOPS FOUND (%d = %s%d, %d = %s%d)!\n",
                       index(flp[i]), sign(flp.def(flp[i]))?"-":"", index(gate(flp.def(flp[i]))),
                       index(flp[j]), sign(flp.def(flp[j]))?"-":"", index(gate(flp.def(flp[j])))
                       );
                goto next_flop;
            }
        keep_flops.push(flp[i]);
    next_flop:;
    }

    map[gate_True] = sig_True;
    for (Gate g = c.firstGate(); g != gate_Undef; g = c.nextGate(g))
        if (type(g) == gtype_And)
            map[g] = to.mkAnd(map[gate(c.lchild(g))] ^ sign(c.lchild(g)),
                              map[gate(c.rchild(g))] ^ sign(c.rchild(g))
                              );

    // Remap inputs, outputs and flops:
    Box   to_box;
    Flops to_flops; to_flops.adjust(to);
    b.remap(map, to_box);
    for (int i = 0; i < keep_flops.size(); i++){
        Gate g = keep_flops[i];
        Sig  x = flp.def(g);
        to_flops.defineFlop(gate(map[g]), map[gate(x)] ^ sign(x));
    }

    // Move circuit back:
    to      .moveTo(c);
    to_box  .moveTo(b);
    to_flops.moveTo(flp);
}

//=================================================================================================
// Functions for moving (pushing/pulling) flops in circuits:

void Minisat::fwdReTime(Circ& c, Box& b, Flops& flp)
{
    mergeEqualFlops(c, b, flp);
    removeDeadFlops(c, b, flp);

    const int max_iters = 3;
    bool shrunk = true;
    for (int iter = 0; shrunk && iter < max_iters; iter++){
        Circ      to;
        Flops     new_flops;
        GMap<Sig> map;
        map.growTo(c.lastGate(), sig_Undef);

        // printf("starting iteration\n");

        // Copy inputs (including flop gates):
        for (int i = 0; i < b.inps.size(); i++) map[b.inps[i]] = to.mkInp();
        for (int i = 0; i < flp.size(); i++)    map[flp[i]]    = to.mkInp();

        // Increase fanouts for all root signals:
        for (int i = 0; i < b.outs.size(); i++) c.bumpFanout(gate(b.outs[i]));
        for (int i = 0; i < flp.size(); i++)    c.bumpFanout(gate(flp.def(flp[i])));

        shrunk = false;
        map[gate_True] = sig_True;
        for (Gate g = c.firstGate(); g != gate_Undef; g = c.nextGate(g))
            if (type(g) == gtype_And)
                if (!retimeable(c, flp, g) && hasInput(c, g, map))
                    map[g] = to.mkAnd(map[gate(c.lchild(g))] ^ sign(c.lchild(g)),
                                      map[gate(c.rchild(g))] ^ sign(c.rchild(g))
                                      );

        for (Gate g = c.firstGate(); g != gate_Undef; g = c.nextGate(g))
            if (type(g) == gtype_And)
                if (retimeable(c, flp, g) && tryReTime(c, flp, to, new_flops, g, map))
                    shrunk = true;
                else{
                    assert(hasInput(c, g, map));
                    map[g] = to.mkAnd(map[gate(c.lchild(g))] ^ sign(c.lchild(g)),
                                      map[gate(c.rchild(g))] ^ sign(c.rchild(g))
                                      );
                }

        // Remap inputs, outputs and flops:
        Box   to_box;
        Flops to_flops;
        b  .remap(map,     to_box);
        flp.remap(to, map, to_flops);

        // Move circuit back:
        to      .moveTo(c);
        to_box  .moveTo(b);
        to_flops.moveTo(flp);

        // Attach new flops:
        flp.adjust(c);
        for (int i = 0; i < new_flops.size(); i++){
            Gate g = new_flops[i];
            Sig  d = new_flops.def(new_flops[i]);
            flp.defineFlop(g, d);
        }

        // Remove dead flops and logic:
        //
        mergeEqualFlops(c, b, flp);
        removeDeadFlops(c, b, flp);
    }
}

void Minisat::bwdReTime(Circ& c, Box& b, Flops& flp)
{
}
<commit_msg>Silence debug prints in Retiming.<commit_after>/****************************************************************************************[ReTime.C]
Copyright (c) 2008, Niklas Sorensson

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.
**************************************************************************************************/

#include "circ/DagShrink.h"
#include "circ/ReTime.h"

using namespace Minisat;

//=================================================================================================
// Helpers:

static inline void removeDeadFlops(Circ& c, Box& b, Flops& flp)
{
    vec<Gate> xs;
    GSet      reached_gates;

    // Calculate all gates reachable from some (real) output:
    //
    for (int i = 0; i < b.outs.size(); i++)
        xs.push(gate(b.outs[i]));

    while (xs.size() > 0){
        Gate g = xs.last(); xs.pop();

        if (reached_gates.has(g))
            continue;
        reached_gates.insert(g);

        assert(g != gate_Undef);
        if (type(g) == gtype_And){
            xs.push(gate(c.lchild(g)));
            xs.push(gate(c.rchild(g)));
        }else if (type(g) == gtype_Inp && flp.isFlop(g))
            xs.push(gate(flp.def(g)));
    }

    // int gates_before = c.nGates();
    // int flops_before = flp.size();
    int inps_before  = b.inps.size();
    int outs_before  = b.outs.size();
    // Create reduced flop set:
    //
    Flops tmp_flops; tmp_flops.adjust(c);
    for (int i = 0; i < flp.size(); i++)
        if (reached_gates.has(flp[i]))
            tmp_flops.defineFlop(flp[i], flp.def(flp[i]));
        // else
        //     printf(" >> FLOP x%d not reached\n", index(flp[i]));
    tmp_flops.moveTo(flp);

    // for (int i = 0; i < flp.size(); i++){
    //     printf("CHECKING FLOP: %d, def = %d\n", index(flp[i]), index(gate(flp.def(flp[i]))));
    //     assert(flp.def(flp[i]) != sig_Undef);
    // }
    assert(inps_before == b.inps.size());
    assert(outs_before == b.outs.size());

    // Remove now dead logic:
    removeDeadLogic(c, b, flp);

    // fprintf(stderr, " >>> REMOVE DEAD FLOPS (before: gates=%d, flops=%d) (after: gates=%d, flops=%d, outs = %d)\n",
    //         gates_before, flops_before, c.nGates(), flp.size(), outs_before);
}

static inline bool retimeable(const Circ& from, const Flops& from_flp, Gate g)
{
    assert(type(g) == gtype_And);

    Gate x = gate(from.lchild(g));
    Gate y = gate(from.rchild(g));

    return type(x) == gtype_Inp && from_flp.isFlop(x)
        && type(y) == gtype_Inp && from_flp.isFlop(y)
        // && (from.nFanouts(x) == 1 || from.nFanouts(y) == 1);
         && from.nFanouts(x) == 1 && from.nFanouts(y) == 1;
}

static inline bool hasInput(const Circ& from, Gate g, const GMap<Sig>& map)
{
    assert(type(g) == gtype_And);

    Gate x = gate(from.lchild(g));
    Gate y = gate(from.rchild(g));

    return map[x] != sig_Undef && map[y] != sig_Undef;
}

static inline bool tryReTime(const Circ& from, const Flops& from_flp, Circ& to, Flops& new_flops, Gate g, GMap<Sig>& map)
{
    assert(type(g) == gtype_And);
    assert(type(from.lchild(g)) == gtype_Inp && from_flp.isFlop(gate(from.lchild(g))));
    assert(type(from.rchild(g)) == gtype_Inp && from_flp.isFlop(gate(from.rchild(g))));

    bool init_val = sign(from.lchild(g)) && sign(from.rchild(g));
    Sig  x_from   = from_flp.def(gate(from.lchild(g))) ^ sign(from.lchild(g));
    Sig  y_from   = from_flp.def(gate(from.rchild(g))) ^ sign(from.rchild(g));

         if (map[gate(x_from)] == sig_Undef) return false;
    else if (map[gate(y_from)] == sig_Undef) return false;

    Sig  x_to     = map[gate(x_from)] ^ sign(x_from);
    Sig  y_to     = map[gate(y_from)] ^ sign(y_from);

    // {
    //     Sig x = from.lchild(g);
    //     Sig y = from.rchild(g);
    //
    //     printf("retiming gate %d:\n", index(g));
    //     printf("...lchild: %s%d\n", sign(x)?"-":"", index(gate(x)));
    //     printf("...rchild: %s%d\n", sign(y)?"-":"", index(gate(y)));
    //     printf("...x_from: %s%d\\%d\n", sign(x_from)?"-":"", index(gate(x_from)), from.nFanouts(gate(x)));
    //     printf("...y_from: %s%d\\%d\n", sign(y_from)?"-":"", index(gate(y_from)), from.nFanouts(gate(y)));
    //     printf("...x_to  : %s%d\n", sign(x_to)?"-":"", index(gate(x_to)));
    //     printf("...y_to  : %s%d\n", sign(y_to)?"-":"", index(gate(y_to)));
    // }

    Sig  next_sig = to.mkAnd(x_to, y_to);
    Gate new_flop = gate(to.mkInp());
    map[g]        = mkSig(new_flop, init_val);

    new_flops.adjust(to);
    new_flops.defineFlop(new_flop, next_sig ^ init_val);

    return true;
}

static inline void mergeEqualFlops(Circ& c, Box& b, Flops& flp)
{
    Circ      to;
    GMap<Sig> map;
    map.growTo(c.lastGate(), sig_Undef);

    // Copy inputs (including flop gates):
    for (int i = 0; i < b.inps.size(); i++) map[b.inps[i]] = to.mkInp();
    for (int i = 0; i < flp.size(); i++)    map[flp[i]]    = to.mkInp();

    vec<Gate> keep_flops;
    for (int i = 0; i < flp.size(); i++){
        for (int j = 0; j < i; j++)
            if (flp.def(flp[j]) == flp.def(flp[i])){
                map[flp[i]] = map[flp[j]];
                // printf(" EQUAL FLOPS FOUND (%d = %s%d, %d = %s%d)!\n",
                //        index(flp[i]), sign(flp.def(flp[i]))?"-":"", index(gate(flp.def(flp[i]))),
                //        index(flp[j]), sign(flp.def(flp[j]))?"-":"", index(gate(flp.def(flp[j])))
                //        );
                goto next_flop;
            }
        keep_flops.push(flp[i]);
    next_flop:;
    }

    map[gate_True] = sig_True;
    for (Gate g = c.firstGate(); g != gate_Undef; g = c.nextGate(g))
        if (type(g) == gtype_And)
            map[g] = to.mkAnd(map[gate(c.lchild(g))] ^ sign(c.lchild(g)),
                              map[gate(c.rchild(g))] ^ sign(c.rchild(g))
                              );

    // Remap inputs, outputs and flops:
    Box   to_box;
    Flops to_flops; to_flops.adjust(to);
    b.remap(map, to_box);
    for (int i = 0; i < keep_flops.size(); i++){
        Gate g = keep_flops[i];
        Sig  x = flp.def(g);
        to_flops.defineFlop(gate(map[g]), map[gate(x)] ^ sign(x));
    }

    // Move circuit back:
    to      .moveTo(c);
    to_box  .moveTo(b);
    to_flops.moveTo(flp);
}

//=================================================================================================
// Functions for moving (pushing/pulling) flops in circuits:

void Minisat::fwdReTime(Circ& c, Box& b, Flops& flp)
{
    mergeEqualFlops(c, b, flp);
    removeDeadFlops(c, b, flp);

    const int max_iters = 3;
    bool shrunk = true;
    for (int iter = 0; shrunk && iter < max_iters; iter++){
        Circ      to;
        Flops     new_flops;
        GMap<Sig> map;
        map.growTo(c.lastGate(), sig_Undef);

        // printf("starting iteration\n");

        // Copy inputs (including flop gates):
        for (int i = 0; i < b.inps.size(); i++) map[b.inps[i]] = to.mkInp();
        for (int i = 0; i < flp.size(); i++)    map[flp[i]]    = to.mkInp();

        // Increase fanouts for all root signals:
        for (int i = 0; i < b.outs.size(); i++) c.bumpFanout(gate(b.outs[i]));
        for (int i = 0; i < flp.size(); i++)    c.bumpFanout(gate(flp.def(flp[i])));

        shrunk = false;
        map[gate_True] = sig_True;
        for (Gate g = c.firstGate(); g != gate_Undef; g = c.nextGate(g))
            if (type(g) == gtype_And)
                if (!retimeable(c, flp, g) && hasInput(c, g, map))
                    map[g] = to.mkAnd(map[gate(c.lchild(g))] ^ sign(c.lchild(g)),
                                      map[gate(c.rchild(g))] ^ sign(c.rchild(g))
                                      );

        for (Gate g = c.firstGate(); g != gate_Undef; g = c.nextGate(g))
            if (type(g) == gtype_And)
                if (retimeable(c, flp, g) && tryReTime(c, flp, to, new_flops, g, map))
                    shrunk = true;
                else{
                    assert(hasInput(c, g, map));
                    map[g] = to.mkAnd(map[gate(c.lchild(g))] ^ sign(c.lchild(g)),
                                      map[gate(c.rchild(g))] ^ sign(c.rchild(g))
                                      );
                }

        // Remap inputs, outputs and flops:
        Box   to_box;
        Flops to_flops;
        b  .remap(map,     to_box);
        flp.remap(to, map, to_flops);

        // Move circuit back:
        to      .moveTo(c);
        to_box  .moveTo(b);
        to_flops.moveTo(flp);

        // Attach new flops:
        flp.adjust(c);
        for (int i = 0; i < new_flops.size(); i++){
            Gate g = new_flops[i];
            Sig  d = new_flops.def(new_flops[i]);
            flp.defineFlop(g, d);
        }

        // Remove dead flops and logic:
        //
        mergeEqualFlops(c, b, flp);
        removeDeadFlops(c, b, flp);
    }
}

void Minisat::bwdReTime(Circ& c, Box& b, Flops& flp)
{
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "vie_autotest_main.h"

#include "gtest/gtest.h"
#include "vie_autotest_window_manager_interface.h"
#include "vie_window_creator.h"
#include "vie_autotest.h"

static const std::string kStandardTest = "ViEStandardIntegrationTest";
static const std::string kExtendedTest = "ViEExtendedIntegrationTest";
static const std::string kApiTest = "ViEApiIntegrationTest";

ViEAutoTestMain::ViEAutoTestMain()
: answers_(),
  answers_count_(0),
  use_answer_file_() {

  index_to_test_method_map_[1] = "RunsBaseTestWithoutErrors";
  index_to_test_method_map_[2] = "RunsCaptureTestWithoutErrors";
  index_to_test_method_map_[3] = "RunsCodecTestWithoutErrors";
  index_to_test_method_map_[4] = "RunsEncryptionTestWithoutErrors";
  index_to_test_method_map_[5] = "RunsFileTestWithoutErrors";
  index_to_test_method_map_[6] = "RunsImageProcessTestWithoutErrors";
  index_to_test_method_map_[7] = "RunsNetworkTestWithoutErrors";
  index_to_test_method_map_[8] = "RunsRenderTestWithoutErrors";
  index_to_test_method_map_[9] = "RunsRtpRtcpTestWithoutErrors";
}

int ViEAutoTestMain::AskUserForTestCase() {
  int choice;
  std::string answer;

  do {
    ViETest::Log("\nSpecific tests:");
    ViETest::Log("\t 0. Go back to previous menu.");

    // Print all test method choices. Assumes that map sorts on its key.
    int last_valid_choice;
    std::map<int, std::string>::const_iterator iterator;
    for (iterator = index_to_test_method_map_.begin();
        iterator != index_to_test_method_map_.end();
        ++iterator) {
      ViETest::Log("\t %d. %s", iterator->first, iterator->second.c_str());
      last_valid_choice = iterator->first;
    }

    ViETest::Log("Choose specific test:");
    choice = AskUserForNumber(0, last_valid_choice);
  } while (choice == kInvalidChoice);

  return choice;
}

int ViEAutoTestMain::AskUserForNumber(int min_allowed, int max_allowed) {
  int result;
  if (use_answer_file_) {
    assert(0 && "Answer files are not implemented");
    return kInvalidChoice;
  }

  if (scanf("%d", &result) <= 0) {
    ViETest::Log("\nPlease enter a number instead, then hit enter.");
    getchar();
    return kInvalidChoice;
  }
  getchar();  // Consume enter key.

  if (result < min_allowed || result > max_allowed) {
    ViETest::Log("%d-%d are valid choices. Please try again.", min_allowed,
                 max_allowed);
    return kInvalidChoice;
  }

  return result;
}

int ViEAutoTestMain::RunTestMatching(const std::string test_case,
                                     const std::string test_method) {
  testing::FLAGS_gtest_filter = test_case + "." + test_method;
  return RUN_ALL_TESTS();
}

int ViEAutoTestMain::RunSpecificTestCaseIn(const std::string test_case_name)
{
  // If user says 0, it means don't run anything.
  int specific_choice = AskUserForTestCase();
  if (specific_choice != 0){
    return RunTestMatching(test_case_name,
                           index_to_test_method_map_[specific_choice]);
  }
  return 0;
}

int ViEAutoTestMain::RunSpecialTestCase(int choice) {
  // 7-9 don't run in GTest and need to initialize by themselves.
  assert(choice >= 7 && choice <= 9);

  // Create the windows
  ViEWindowCreator windowCreator;
  ViEAutoTestWindowManagerInterface* windowManager =
      windowCreator.CreateTwoWindows();

  // Create the test cases
  ViEAutoTest vieAutoTest(windowManager->GetWindow1(),
                          windowManager->GetWindow2());

  int errors;
  switch (choice) {
    case 7: errors = vieAutoTest.ViELoopbackCall();  break;
    case 8: errors = vieAutoTest.ViECustomCall();    break;
    case 9: errors = vieAutoTest.ViESimulcastCall(); break;
  }

  windowCreator.TerminateWindows();
  return errors;
}

bool ViEAutoTestMain::BeginOSIndependentTesting() {

  ViETest::Log(" ============================== ");
  ViETest::Log("    WebRTC ViE 3.x Autotest     ");
  ViETest::Log(" ============================== \n");

  int choice = 0;
  int errors = 0;
  do {
    ViETest::Log("Test types: ");
    ViETest::Log("\t 0. Quit");
    ViETest::Log("\t 1. All standard tests (delivery test)");
    ViETest::Log("\t 2. All API tests");
    ViETest::Log("\t 3. All extended test");
    ViETest::Log("\t 4. Specific standard test");
    ViETest::Log("\t 5. Specific API test");
    ViETest::Log("\t 6. Specific extended test");
    ViETest::Log("\t 7. Simple loopback call");
    ViETest::Log("\t 8. Custom configure a call");
    ViETest::Log("\t 9. Simulcast in loopback");
    ViETest::Log("Select type of test:");

    choice = AskUserForNumber(0, 9);
    if (choice == kInvalidChoice) {
      continue;
    }
    switch (choice) {
      case 0:                                                 break;
      case 1:  errors = RunTestMatching(kStandardTest, "*");  break;
      case 2:  errors = RunTestMatching(kApiTest,      "*");  break;
      case 3:  errors = RunTestMatching(kExtendedTest, "*");  break;
      case 4:  errors = RunSpecificTestCaseIn(kStandardTest); break;
      case 5:  errors = RunSpecificTestCaseIn(kApiTest);      break;
      case 6:  errors = RunSpecificTestCaseIn(kExtendedTest); break;
      default: errors = RunSpecialTestCase(choice);           break;
    }
  } while (choice != 0);

  if (errors) {
    ViETest::Log("Test done with errors, see ViEAutotestLog.txt for test "
        "result.\n");
  } else {
    ViETest::Log("Test done without errors, see ViEAutotestLog.txt for "
        "test result.\n");
  }
  return true;
}

bool ViEAutoTestMain::GetAnswer(int index, std::string* answer) {
  if (!use_answer_file_ || index > answers_count_) {
    return false;
  }
  *answer = answers_[index];
  return true;
}

bool ViEAutoTestMain::IsUsingAnswerFile() {
  return use_answer_file_;
}

// TODO(unknown): implement?
bool ViEAutoTestMain::UseAnswerFile(const char* fileName) {
  return false;
/*
     use_answer_file_ = false;

     ViETest::Log("Opening answer file:  %s...", fileName);

     ifstream answerFile(fileName);
     if(!answerFile)
     {
       ViETest::Log("failed! X(\n");
       return false;
     }

     answers_count_ = 1;
     answers_index_ = 1;
     char lineContent[128] = "";
     while(!answerFile.eof())
     {
       answerFile.getline(lineContent, 128);
       answers_[answers_Count++] = string(lineContent);
     }
     answerFile.close();

     cout << "Success :)" << endl << endl;

     use_answer_file_ = true;

     return use_answer_file_;
*/
}
<commit_msg>Fixed release compilation error-warnings.<commit_after>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "vie_autotest_main.h"

#include "gtest/gtest.h"
#include "vie_autotest_window_manager_interface.h"
#include "vie_window_creator.h"
#include "vie_autotest.h"

static const std::string kStandardTest = "ViEStandardIntegrationTest";
static const std::string kExtendedTest = "ViEExtendedIntegrationTest";
static const std::string kApiTest = "ViEApiIntegrationTest";

ViEAutoTestMain::ViEAutoTestMain()
: answers_(),
  answers_count_(0),
  use_answer_file_() {

  index_to_test_method_map_[1] = "RunsBaseTestWithoutErrors";
  index_to_test_method_map_[2] = "RunsCaptureTestWithoutErrors";
  index_to_test_method_map_[3] = "RunsCodecTestWithoutErrors";
  index_to_test_method_map_[4] = "RunsEncryptionTestWithoutErrors";
  index_to_test_method_map_[5] = "RunsFileTestWithoutErrors";
  index_to_test_method_map_[6] = "RunsImageProcessTestWithoutErrors";
  index_to_test_method_map_[7] = "RunsNetworkTestWithoutErrors";
  index_to_test_method_map_[8] = "RunsRenderTestWithoutErrors";
  index_to_test_method_map_[9] = "RunsRtpRtcpTestWithoutErrors";
}

int ViEAutoTestMain::AskUserForTestCase() {
  int choice;
  std::string answer;

  do {
    ViETest::Log("\nSpecific tests:");
    ViETest::Log("\t 0. Go back to previous menu.");

    // Print all test method choices. Assumes that map sorts on its key.
    int last_valid_choice = 0;
    std::map<int, std::string>::const_iterator iterator;
    for (iterator = index_to_test_method_map_.begin();
        iterator != index_to_test_method_map_.end();
        ++iterator) {
      ViETest::Log("\t %d. %s", iterator->first, iterator->second.c_str());
      last_valid_choice = iterator->first;
    }

    ViETest::Log("Choose specific test:");
    choice = AskUserForNumber(0, last_valid_choice);
  } while (choice == kInvalidChoice);

  return choice;
}

int ViEAutoTestMain::AskUserForNumber(int min_allowed, int max_allowed) {
  int result;
  if (use_answer_file_) {
    assert(0 && "Answer files are not implemented");
    return kInvalidChoice;
  }

  if (scanf("%d", &result) <= 0) {
    ViETest::Log("\nPlease enter a number instead, then hit enter.");
    getchar();
    return kInvalidChoice;
  }
  getchar();  // Consume enter key.

  if (result < min_allowed || result > max_allowed) {
    ViETest::Log("%d-%d are valid choices. Please try again.", min_allowed,
                 max_allowed);
    return kInvalidChoice;
  }

  return result;
}

int ViEAutoTestMain::RunTestMatching(const std::string test_case,
                                     const std::string test_method) {
  testing::FLAGS_gtest_filter = test_case + "." + test_method;
  return RUN_ALL_TESTS();
}

int ViEAutoTestMain::RunSpecificTestCaseIn(const std::string test_case_name)
{
  // If user says 0, it means don't run anything.
  int specific_choice = AskUserForTestCase();
  if (specific_choice != 0){
    return RunTestMatching(test_case_name,
                           index_to_test_method_map_[specific_choice]);
  }
  return 0;
}

int ViEAutoTestMain::RunSpecialTestCase(int choice) {
  // 7-9 don't run in GTest and need to initialize by themselves.
  assert(choice >= 7 && choice <= 9);

  // Create the windows
  ViEWindowCreator windowCreator;
  ViEAutoTestWindowManagerInterface* windowManager =
      windowCreator.CreateTwoWindows();

  // Create the test cases
  ViEAutoTest vieAutoTest(windowManager->GetWindow1(),
                          windowManager->GetWindow2());

  int errors = 0;
  switch (choice) {
    case 7: errors = vieAutoTest.ViELoopbackCall();  break;
    case 8: errors = vieAutoTest.ViECustomCall();    break;
    case 9: errors = vieAutoTest.ViESimulcastCall(); break;
  }

  windowCreator.TerminateWindows();
  return errors;
}

bool ViEAutoTestMain::BeginOSIndependentTesting() {

  ViETest::Log(" ============================== ");
  ViETest::Log("    WebRTC ViE 3.x Autotest     ");
  ViETest::Log(" ============================== \n");

  int choice = 0;
  int errors = 0;
  do {
    ViETest::Log("Test types: ");
    ViETest::Log("\t 0. Quit");
    ViETest::Log("\t 1. All standard tests (delivery test)");
    ViETest::Log("\t 2. All API tests");
    ViETest::Log("\t 3. All extended test");
    ViETest::Log("\t 4. Specific standard test");
    ViETest::Log("\t 5. Specific API test");
    ViETest::Log("\t 6. Specific extended test");
    ViETest::Log("\t 7. Simple loopback call");
    ViETest::Log("\t 8. Custom configure a call");
    ViETest::Log("\t 9. Simulcast in loopback");
    ViETest::Log("Select type of test:");

    choice = AskUserForNumber(0, 9);
    if (choice == kInvalidChoice) {
      continue;
    }
    switch (choice) {
      case 0:                                                 break;
      case 1:  errors = RunTestMatching(kStandardTest, "*");  break;
      case 2:  errors = RunTestMatching(kApiTest,      "*");  break;
      case 3:  errors = RunTestMatching(kExtendedTest, "*");  break;
      case 4:  errors = RunSpecificTestCaseIn(kStandardTest); break;
      case 5:  errors = RunSpecificTestCaseIn(kApiTest);      break;
      case 6:  errors = RunSpecificTestCaseIn(kExtendedTest); break;
      default: errors = RunSpecialTestCase(choice);           break;
    }
  } while (choice != 0);

  if (errors) {
    ViETest::Log("Test done with errors, see ViEAutotestLog.txt for test "
        "result.\n");
  } else {
    ViETest::Log("Test done without errors, see ViEAutotestLog.txt for "
        "test result.\n");
  }
  return true;
}

bool ViEAutoTestMain::GetAnswer(int index, std::string* answer) {
  if (!use_answer_file_ || index > answers_count_) {
    return false;
  }
  *answer = answers_[index];
  return true;
}

bool ViEAutoTestMain::IsUsingAnswerFile() {
  return use_answer_file_;
}

// TODO(unknown): implement?
bool ViEAutoTestMain::UseAnswerFile(const char* fileName) {
  return false;
/*
     use_answer_file_ = false;

     ViETest::Log("Opening answer file:  %s...", fileName);

     ifstream answerFile(fileName);
     if(!answerFile)
     {
       ViETest::Log("failed! X(\n");
       return false;
     }

     answers_count_ = 1;
     answers_index_ = 1;
     char lineContent[128] = "";
     while(!answerFile.eof())
     {
       answerFile.getline(lineContent, 128);
       answers_[answers_Count++] = string(lineContent);
     }
     answerFile.close();

     cout << "Success :)" << endl << endl;

     use_answer_file_ = true;

     return use_answer_file_;
*/
}
<|endoftext|>


<commit_before><commit_msg>clean compile<commit_after><|endoftext|>


<commit_before>//===--- PTHLexer.cpp - Lex from a token stream ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PTHLexer interface.
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TokenKinds.h"
using namespace clang;

PTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc,
                   const Token *TokArray, unsigned NumTokens)
  : PreprocessorLexer(&pp, fileloc),
    Tokens(TokArray),
    LastTokenIdx(NumTokens - 1),
    CurTokenIdx(0) {

  assert(NumTokens >= 1);
  assert(Tokens[LastTokenIdx].is(tok::eof));
}

Token PTHLexer::GetToken() {
  Token Tok = Tokens[CurTokenIdx];

  // If we are in raw mode, zero out identifier pointers.  This is
  // needed for 'pragma poison'.  Note that this requires that the Preprocessor
  // can go back to the original source when it calls getSpelling().
  if (LexingRawMode && Tok.is(tok::identifier))
    Tok.setIdentifierInfo(0);

  return Tok;
}

void PTHLexer::Lex(Token& Tok) {
LexNextToken:
  Tok = GetToken();

  if (AtLastToken()) {
    Preprocessor *PPCache = PP;

    if (LexEndOfFile(Tok))
      return;

    assert(PPCache && "Raw buffer::LexEndOfFile should return a token");
    return PPCache->Lex(Tok);
  }

  // Don't advance to the next token yet.  Check if we are at the
  // start of a new line and we're processing a directive.  If so, we
  // consume this token twice, once as an tok::eom.
  if (Tok.isAtStartOfLine() && ParsingPreprocessorDirective) {
    ParsingPreprocessorDirective = false;
    Tok.setKind(tok::eom);
    MIOpt.ReadToken();
    return;
  }

  // Advance to the next token.
  AdvanceToken();

  if (Tok.is(tok::hash)) {
    if (Tok.isAtStartOfLine() && !LexingRawMode) {
      PP->HandleDirective(Tok);

      if (PP->isCurrentLexer(this))
        goto LexNextToken;

      return PP->Lex(Tok);
    }
  }

  MIOpt.ReadToken();

  if (Tok.is(tok::identifier)) {
    if (LexingRawMode) return;
    return PP->HandleIdentifier(Tok);
  }
}

bool PTHLexer::LexEndOfFile(Token &Tok) {

  if (ParsingPreprocessorDirective) {
    ParsingPreprocessorDirective = false;
    Tok.setKind(tok::eom);
    MIOpt.ReadToken();
    return true; // Have a token.
  }

  if (LexingRawMode) {
    MIOpt.ReadToken();
    return true;  // Have an eof token.
  }

  // FIXME: Issue diagnostics similar to Lexer.
  return PP->HandleEndOfFile(Tok, false);
}

void PTHLexer::setEOF(Token& Tok) {
  Tok = Tokens[LastTokenIdx];
}

void PTHLexer::DiscardToEndOfLine() {
  assert(ParsingPreprocessorDirective && ParsingFilename == false &&
         "Must be in a preprocessing directive!");

  // Already at end-of-file?
  if (AtLastToken())
    return;

  // Find the first token that is not the start of the *current* line.
  for (AdvanceToken(); !AtLastToken(); AdvanceToken())
    if (GetToken().isAtStartOfLine())
      return;
}
<commit_msg>In PTHLexer::DiscardToEndOfLine() use Lex() instead of AdvanceToken().  This handles transitions in the preprocessor state.<commit_after>//===--- PTHLexer.cpp - Lex from a token stream ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PTHLexer interface.
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/TokenKinds.h"
using namespace clang;

PTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc,
                   const Token *TokArray, unsigned NumTokens)
  : PreprocessorLexer(&pp, fileloc),
    Tokens(TokArray),
    LastTokenIdx(NumTokens - 1),
    CurTokenIdx(0) {

  assert(NumTokens >= 1);
  assert(Tokens[LastTokenIdx].is(tok::eof));
}

Token PTHLexer::GetToken() {
  Token Tok = Tokens[CurTokenIdx];

  // If we are in raw mode, zero out identifier pointers.  This is
  // needed for 'pragma poison'.  Note that this requires that the Preprocessor
  // can go back to the original source when it calls getSpelling().
  if (LexingRawMode && Tok.is(tok::identifier))
    Tok.setIdentifierInfo(0);

  return Tok;
}

void PTHLexer::Lex(Token& Tok) {
LexNextToken:
  Tok = GetToken();

  if (AtLastToken()) {
    Preprocessor *PPCache = PP;

    if (LexEndOfFile(Tok))
      return;

    assert(PPCache && "Raw buffer::LexEndOfFile should return a token");
    return PPCache->Lex(Tok);
  }

  // Don't advance to the next token yet.  Check if we are at the
  // start of a new line and we're processing a directive.  If so, we
  // consume this token twice, once as an tok::eom.
  if (Tok.isAtStartOfLine() && ParsingPreprocessorDirective) {
    ParsingPreprocessorDirective = false;
    Tok.setKind(tok::eom);
    MIOpt.ReadToken();
    return;
  }

  // Advance to the next token.
  AdvanceToken();

  if (Tok.is(tok::hash)) {
    if (Tok.isAtStartOfLine() && !LexingRawMode) {
      PP->HandleDirective(Tok);

      if (PP->isCurrentLexer(this))
        goto LexNextToken;

      return PP->Lex(Tok);
    }
  }

  MIOpt.ReadToken();

  if (Tok.is(tok::identifier)) {
    if (LexingRawMode) return;
    return PP->HandleIdentifier(Tok);
  }
}

bool PTHLexer::LexEndOfFile(Token &Tok) {

  if (ParsingPreprocessorDirective) {
    ParsingPreprocessorDirective = false;
    Tok.setKind(tok::eom);
    MIOpt.ReadToken();
    return true; // Have a token.
  }

  if (LexingRawMode) {
    MIOpt.ReadToken();
    return true;  // Have an eof token.
  }

  // FIXME: Issue diagnostics similar to Lexer.
  return PP->HandleEndOfFile(Tok, false);
}

void PTHLexer::setEOF(Token& Tok) {
  Tok = Tokens[LastTokenIdx];
}

void PTHLexer::DiscardToEndOfLine() {
  assert(ParsingPreprocessorDirective && ParsingFilename == false &&
         "Must be in a preprocessing directive!");

  // Already at end-of-file?
  if (AtLastToken())
    return;

  // Find the first token that is not the start of the *current* line.
  Token T;
  for (Lex(T); !AtLastToken(); Lex(T))
    if (GetToken().isAtStartOfLine())
      return;
}
<|endoftext|>


<commit_before><commit_msg>Forward port of:<commit_after><|endoftext|>