<commit_before>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "filesearch.h"

#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QFutureInterface>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QRegExp>
#include <QtGui/QApplication>

#include <qtconcurrent/runextensions.h>

using namespace Core::Utils;

namespace {

void runFileSearch(QFutureInterface<FileSearchResult> &future,
                   QString searchTerm,
                   QStringList files,
                   QTextDocument::FindFlags flags)
{
    future.setProgressRange(0, files.size());
    int numFilesSearched = 0;
    int numMatches = 0;

    bool caseInsensitive = !(flags & QTextDocument::FindCaseSensitively);
    bool wholeWord = (flags & QTextDocument::FindWholeWords);

    QByteArray sa = searchTerm.toUtf8();
    int scMaxIndex = sa.length()-1;
    const char *sc = sa.constData();

    QByteArray sal = searchTerm.toLower().toUtf8();
    const char *scl = sal.constData();

    QByteArray sau = searchTerm.toUpper().toUtf8();
    const char *scu = sau.constData();

    int chunkSize = qMax(100000, sa.length());

    foreach (QString s, files) {
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(numFilesSearched,
                                           qApp->translate("FileSearch", "%1: canceled. %2 occurrences found in %3 files.").
                                           arg(searchTerm).arg(numMatches).arg(numFilesSearched));
            break;
        }
        QFile file(s);
        if (!file.open(QIODevice::ReadOnly))
            continue;
        int lineNr = 1;
        const char *startOfLastLine = NULL;

        bool firstChunk = true;
        while (!file.atEnd()) {
            if (!firstChunk)
                file.seek(file.pos()-sa.length()+1);

            const QByteArray chunk = file.read(chunkSize);
            const char *chunkPtr = chunk.constData();
            startOfLastLine = chunkPtr;
            for (const char *regionPtr = chunkPtr; regionPtr < chunkPtr + chunk.length()-scMaxIndex; ++regionPtr) {
                const char *regionEnd = regionPtr + scMaxIndex;

                if (*regionPtr == '\n') {
                    startOfLastLine = regionPtr + 1;
                    ++lineNr;
                }
                else if (
                        // case sensitive
                        (!caseInsensitive && *regionPtr == sc[0] && *regionEnd == sc[scMaxIndex])
                        ||
                        // case insensitive
                        (caseInsensitive && (*regionPtr == scl[0] || *regionPtr == scu[0])
                        && (*regionEnd == scl[scMaxIndex] || *regionEnd == scu[scMaxIndex]))
                         ) {
                    const char *afterRegion = regionEnd + 1;
                    const char *beforeRegion = regionPtr - 1;
                    bool equal = true;
                    if (wholeWord &&
                        ( ((*beforeRegion >= '0' && *beforeRegion <= '9') || *beforeRegion >= 'A')
                        || ((*afterRegion >= '0' && *afterRegion <= '9') || *afterRegion >= 'A')))
                    {
                        equal = false;
                    }

                    int regionIndex = 1;
                    for (const char *regionCursor = regionPtr + 1; regionCursor < regionEnd; ++regionCursor, ++regionIndex) {
                        if (  // case sensitive
                              (!caseInsensitive && equal && *regionCursor != sc[regionIndex])
                              ||
                              // case insensitive
                              (caseInsensitive && equal && *regionCursor != sc[regionIndex] && *regionCursor != scl[regionIndex] && *regionCursor != scu[regionIndex])
                               ) {
                         equal = false;
                        }
                    }
                    if (equal) {
                        int textLength = chunk.length() - (startOfLastLine - chunkPtr);
                        if (textLength > 0) {
                            QByteArray res;
                            res.reserve(256);
                            int i = 0;
                            int n = 0;
                            while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256)
                                res.append(startOfLastLine[i++]);
                            future.reportResult(FileSearchResult(QDir::toNativeSeparators(s), lineNr, QString(res),
                                                          regionPtr - startOfLastLine, sa.length()));
                            ++numMatches;
                        }
                    }
                }
            }
            firstChunk = false;
        }
        ++numFilesSearched;
        future.setProgressValueAndText(numFilesSearched, qApp->translate("FileSearch", "%1: %2 occurrences found in %3 of %4 files.").
                                arg(searchTerm).arg(numMatches).arg(numFilesSearched).arg(files.size()));
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(numFilesSearched, qApp->translate("FileSearch", "%1: %2 occurrences found in %3 files.").
                                arg(searchTerm).arg(numMatches).arg(numFilesSearched));
}

void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
                   QString searchTerm,
                   QStringList files,
                   QTextDocument::FindFlags flags)
{
    future.setProgressRange(0, files.size());
    int numFilesSearched = 0;
    int numMatches = 0;
    if (flags & QTextDocument::FindWholeWords)
        searchTerm = QString("\b%1\b").arg(searchTerm);
    Qt::CaseSensitivity caseSensitivity = (flags & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive;
    QRegExp expression(searchTerm, caseSensitivity);

    foreach (QString s, files) {
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(numFilesSearched,
                                           qApp->translate("FileSearch", "%1: canceled. %2 occurrences found in %3 files.").
                                           arg(searchTerm).arg(numMatches).arg(numFilesSearched));
            break;
        }
        QFile file(s);
        if (!file.open(QIODevice::ReadOnly))
            continue;
        QTextStream stream(&file);
        int lineNr = 1;
        QString line;
        while (!stream.atEnd()) {
            line = stream.readLine();
            int pos = 0;
            while ((pos = expression.indexIn(line, pos)) != -1) {
                future.reportResult(FileSearchResult(QDir::toNativeSeparators(s), lineNr, line,
                                              pos, expression.matchedLength()));
                pos += expression.matchedLength();
            }
            ++lineNr;
        }
        ++numFilesSearched;
        future.setProgressValueAndText(numFilesSearched, qApp->translate("FileSearch", "%1: %2 occurrences found in %3 of %4 files.").
                                arg(searchTerm).arg(numMatches).arg(numFilesSearched).arg(files.size()));
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(numFilesSearched, qApp->translate("FileSearch", "%1: %2 occurrences found in %3 files.").
                                arg(searchTerm).arg(numMatches).arg(numFilesSearched));
}

} // namespace

QFuture<FileSearchResult> Core::Utils::findInFiles(const QString &searchTerm, const QStringList &files,
    QTextDocument::FindFlags flags)
{
    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags>(runFileSearch, searchTerm, files, flags);
}

QFuture<FileSearchResult> Core::Utils::findInFilesRegExp(const QString &searchTerm, const QStringList &files,
    QTextDocument::FindFlags flags)
{
    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags>(runFileSearchRegExp, searchTerm, files, flags);
}
<commit_msg>escape backslash => make "whole words only" work with "regular expression"<commit_after>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 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 GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "filesearch.h"

#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QFutureInterface>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QRegExp>
#include <QtGui/QApplication>

#include <qtconcurrent/runextensions.h>

using namespace Core::Utils;

namespace {

void runFileSearch(QFutureInterface<FileSearchResult> &future,
                   QString searchTerm,
                   QStringList files,
                   QTextDocument::FindFlags flags)
{
    future.setProgressRange(0, files.size());
    int numFilesSearched = 0;
    int numMatches = 0;

    bool caseInsensitive = !(flags & QTextDocument::FindCaseSensitively);
    bool wholeWord = (flags & QTextDocument::FindWholeWords);

    QByteArray sa = searchTerm.toUtf8();
    int scMaxIndex = sa.length()-1;
    const char *sc = sa.constData();

    QByteArray sal = searchTerm.toLower().toUtf8();
    const char *scl = sal.constData();

    QByteArray sau = searchTerm.toUpper().toUtf8();
    const char *scu = sau.constData();

    int chunkSize = qMax(100000, sa.length());

    foreach (QString s, files) {
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(numFilesSearched,
                                           qApp->translate("FileSearch", "%1: canceled. %2 occurrences found in %3 files.").
                                           arg(searchTerm).arg(numMatches).arg(numFilesSearched));
            break;
        }
        QFile file(s);
        if (!file.open(QIODevice::ReadOnly))
            continue;
        int lineNr = 1;
        const char *startOfLastLine = NULL;

        bool firstChunk = true;
        while (!file.atEnd()) {
            if (!firstChunk)
                file.seek(file.pos()-sa.length()+1);

            const QByteArray chunk = file.read(chunkSize);
            const char *chunkPtr = chunk.constData();
            startOfLastLine = chunkPtr;
            for (const char *regionPtr = chunkPtr; regionPtr < chunkPtr + chunk.length()-scMaxIndex; ++regionPtr) {
                const char *regionEnd = regionPtr + scMaxIndex;

                if (*regionPtr == '\n') {
                    startOfLastLine = regionPtr + 1;
                    ++lineNr;
                }
                else if (
                        // case sensitive
                        (!caseInsensitive && *regionPtr == sc[0] && *regionEnd == sc[scMaxIndex])
                        ||
                        // case insensitive
                        (caseInsensitive && (*regionPtr == scl[0] || *regionPtr == scu[0])
                        && (*regionEnd == scl[scMaxIndex] || *regionEnd == scu[scMaxIndex]))
                         ) {
                    const char *afterRegion = regionEnd + 1;
                    const char *beforeRegion = regionPtr - 1;
                    bool equal = true;
                    if (wholeWord &&
                        ( ((*beforeRegion >= '0' && *beforeRegion <= '9') || *beforeRegion >= 'A')
                        || ((*afterRegion >= '0' && *afterRegion <= '9') || *afterRegion >= 'A')))
                    {
                        equal = false;
                    }

                    int regionIndex = 1;
                    for (const char *regionCursor = regionPtr + 1; regionCursor < regionEnd; ++regionCursor, ++regionIndex) {
                        if (  // case sensitive
                              (!caseInsensitive && equal && *regionCursor != sc[regionIndex])
                              ||
                              // case insensitive
                              (caseInsensitive && equal && *regionCursor != sc[regionIndex] && *regionCursor != scl[regionIndex] && *regionCursor != scu[regionIndex])
                               ) {
                         equal = false;
                        }
                    }
                    if (equal) {
                        int textLength = chunk.length() - (startOfLastLine - chunkPtr);
                        if (textLength > 0) {
                            QByteArray res;
                            res.reserve(256);
                            int i = 0;
                            int n = 0;
                            while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256)
                                res.append(startOfLastLine[i++]);
                            future.reportResult(FileSearchResult(QDir::toNativeSeparators(s), lineNr, QString(res),
                                                          regionPtr - startOfLastLine, sa.length()));
                            ++numMatches;
                        }
                    }
                }
            }
            firstChunk = false;
        }
        ++numFilesSearched;
        future.setProgressValueAndText(numFilesSearched, qApp->translate("FileSearch", "%1: %2 occurrences found in %3 of %4 files.").
                                arg(searchTerm).arg(numMatches).arg(numFilesSearched).arg(files.size()));
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(numFilesSearched, qApp->translate("FileSearch", "%1: %2 occurrences found in %3 files.").
                                arg(searchTerm).arg(numMatches).arg(numFilesSearched));
}

void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
                   QString searchTerm,
                   QStringList files,
                   QTextDocument::FindFlags flags)
{
    future.setProgressRange(0, files.size());
    int numFilesSearched = 0;
    int numMatches = 0;
    if (flags & QTextDocument::FindWholeWords)
        searchTerm = QString("\\b%1\\b").arg(searchTerm);
    Qt::CaseSensitivity caseSensitivity = (flags & QTextDocument::FindCaseSensitively) ? Qt::CaseSensitive : Qt::CaseInsensitive;
    QRegExp expression(searchTerm, caseSensitivity);

    foreach (QString s, files) {
        if (future.isPaused())
            future.waitForResume();
        if (future.isCanceled()) {
            future.setProgressValueAndText(numFilesSearched,
                                           qApp->translate("FileSearch", "%1: canceled. %2 occurrences found in %3 files.").
                                           arg(searchTerm).arg(numMatches).arg(numFilesSearched));
            break;
        }
        QFile file(s);
        if (!file.open(QIODevice::ReadOnly))
            continue;
        QTextStream stream(&file);
        int lineNr = 1;
        QString line;
        while (!stream.atEnd()) {
            line = stream.readLine();
            int pos = 0;
            while ((pos = expression.indexIn(line, pos)) != -1) {
                future.reportResult(FileSearchResult(QDir::toNativeSeparators(s), lineNr, line,
                                              pos, expression.matchedLength()));
                pos += expression.matchedLength();
            }
            ++lineNr;
        }
        ++numFilesSearched;
        future.setProgressValueAndText(numFilesSearched, qApp->translate("FileSearch", "%1: %2 occurrences found in %3 of %4 files.").
                                arg(searchTerm).arg(numMatches).arg(numFilesSearched).arg(files.size()));
    }
    if (!future.isCanceled())
        future.setProgressValueAndText(numFilesSearched, qApp->translate("FileSearch", "%1: %2 occurrences found in %3 files.").
                                arg(searchTerm).arg(numMatches).arg(numFilesSearched));
}

} // namespace

QFuture<FileSearchResult> Core::Utils::findInFiles(const QString &searchTerm, const QStringList &files,
    QTextDocument::FindFlags flags)
{
    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags>(runFileSearch, searchTerm, files, flags);
}

QFuture<FileSearchResult> Core::Utils::findInFilesRegExp(const QString &searchTerm, const QStringList &files,
    QTextDocument::FindFlags flags)
{
    return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags>(runFileSearchRegExp, searchTerm, files, flags);
}
<|endoftext|>


<commit_before>/* $Id: middlewareSubscriptionTests.cpp,v 1.1.2.5 2012/12/17 15:46:04 matthewmulhern Exp $
 *
 * OpenMAMA: The open middleware agnostic messaging API
 * Copyright (C) 2011 NYSE Technologies, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include <gtest/gtest.h>
#include "mama/mama.h"
#include "MainUnitTestC.h"
#include <iostream>
#include "bridge.h"
#include "mama/types.h"

using std::cout;
using std::endl;

static void onCreate (mamaSubscription subscription, void* closure);

static void onError(mamaSubscription subscription,
                    mama_status      status,
                    void*            platformError,
                    const char*      subject,
                    void*            closure);

static void onQuality(mamaSubscription subsc,
                      mamaQuality      quality,
                      const char*      symbol,
                      short            cause,
                      const void*      platformInfo,
                      void*            closure);

static void onMsg(mamaSubscription subscription,
                  mamaMsg          msg,
                  void*            closure,
                  void*            itemClosure);

static void onGap(mamaSubscription subsc, void* closure);
static void onRecapRequest(mamaSubscription subsc, void* closure);
static void onDestroy(mamaSubscription subsc, void* closure);

class MiddlewareSubscriptionTests : public ::testing::Test
{
protected:
    MiddlewareSubscriptionTests(void);
    virtual ~MiddlewareSubscriptionTests(void);

    virtual void SetUp(void);
    virtual void TearDown(void);

    mamaBridge mBridge;
    mamaTransport tport;
    const char*   tportName;

    subscriptionBridge subscriber;
    mamaSource         source;
    const char*        sourceName;
    const char*        symbol;
    mamaQueue          queue;
    void*              closure;
    mamaSubscription   parent;
    mamaMsgCallbacks   callbacks;
};

MiddlewareSubscriptionTests::MiddlewareSubscriptionTests(void)
    : tport (NULL),
      tportName ("test_tport"),
      source (NULL),
      sourceName ("src"),
      symbol ("SYM"),
      queue (NULL),
      closure (NULL)
{
    mama_loadBridge (&mBridge, getMiddleware());

    mamaQueue_create(&queue, mBridge);
}

MiddlewareSubscriptionTests::~MiddlewareSubscriptionTests(void)
{
    mamaQueue_destroy (queue);
}

void MiddlewareSubscriptionTests::SetUp(void)
{
    mama_open();  /* Forces loading of entitlements bridges as necessary */
    mamaTransport_allocate (&tport);
    mamaTransport_create   (tport, tportName, mBridge);

    mamaSource_create(&source);
    mamaSource_setId(source, "SRC");
    mamaSource_setTransport(source, tport);
    mamaSource_setSymbolNamespace(source, "NASDAQ");

    mamaSubscription_allocate(&parent);

    callbacks.onCreate          = onCreate;
    callbacks.onError           = onError;
    callbacks.onQuality         = onQuality;
    callbacks.onMsg             = onMsg;
    callbacks.onGap             = onGap;
    callbacks.onRecapRequest    = onRecapRequest;
    callbacks.onDestroy         = onDestroy;
}

void MiddlewareSubscriptionTests::TearDown(void)
{
    mamaTransport_destroy (tport);
    mamaSubscription_deallocate(parent);
    mama_close();
}

static void onCreate (mamaSubscription subscription,
                      void* closure)
{
}

static void onError(mamaSubscription subscription,
                    mama_status      status,
                    void*            platformError,
                    const char*      subject,
                    void*            closure)
{
}

static void onQuality(mamaSubscription subsc,
                      mamaQuality      quality,
                      const char*      symbol,
                      short            cause,
                      const void*      platformInfo,
                      void*            closure)
{
}

static void onMsg(mamaSubscription subscription,
                  mamaMsg          msg,
                  void*            closure,
                  void*            itemClosure)
{
}

static void onGap(mamaSubscription subsc, void* closure)
{
}

static void onRecapRequest(mamaSubscription subsc, void* closure)
{
}

static void onDestroy(mamaSubscription subsc, void* closure)
{
}

/*===================================================================
 =               mamaSubscription bridge functions                   =
 ====================================================================*/

/* TODO:
 * Discuss the validity of these tests - ultimately we double create
 * subscriptions, which I would assume isn't supposed to be expected behaviour.
 */
TEST_F (MiddlewareSubscriptionTests, DISABLED_createDestroy)
/* cores*/
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));

    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_destroy(parent));

    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_deallocate(parent));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidResult)
{
    ASSERT_EQ(MAMA_STATUS_NULL_ARG,
              mBridge->bridgeMamaSubscriptionCreate(NULL, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidTport)
{
    ASSERT_EQ(MAMA_STATUS_NULL_ARG,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    NULL, queue, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidSourceName)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, NULL, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidSymbol)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, NULL,
                                                    tport, queue, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidQueue)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, NULL, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidParent)
{
    ASSERT_EQ(MAMA_STATUS_NULL_ARG,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    NULL, closure));
}
/* TEST COMMENTED OUT BECAUSE mamaMsgCallbacks CAN'T BE CAST AS NULL!
TEST_F (MiddlewareSubscriptionTests, createInvalidCallbacks)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, NULL,
                                                    parent, closure));
}
*/

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidResult)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(NULL, sourceName, symbol,
                                                            tport, queue, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidSource)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, NULL, symbol,
                                                            tport, queue, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidSymbol)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, NULL,
                                                            tport, queue, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidTport)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, symbol,
                                                            NULL, queue, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidQueue)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, symbol,
                                                            tport, NULL, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidParent)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, symbol,
                                                            tport, queue, callbacks,
                                                            NULL, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
              status);
}
/* COMMENTED OUT BECAUSE mamaMsg Callbacks CAN'T BE CAST AS NULL
TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidCallbacks)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, symbol,
                                                            tport, queue, NULL,
                                                            parent, closure));
}
*/

TEST_F (MiddlewareSubscriptionTests, mute)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));

    ASSERT_EQ (MAMA_STATUS_OK,
               mBridge->bridgeMamaSubscriptionMute(subscriber));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));
}

TEST_F (MiddlewareSubscriptionTests, muteInvalid)
{
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               mBridge->bridgeMamaSubscriptionMute(NULL));
}

TEST_F (MiddlewareSubscriptionTests, destroyInvalid)
{
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               mBridge->bridgeMamaSubscriptionDestroy(NULL));
}

TEST_F (MiddlewareSubscriptionTests, isValid)
{
    int res = NULL;
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));

    res = mBridge->bridgeMamaSubscriptionIsValid(subscriber);
    ASSERT_TRUE(res != NULL);

}

TEST_F (MiddlewareSubscriptionTests, isValidInvalid)
{
    int res = NULL;

    res = mBridge->bridgeMamaSubscriptionIsValid(NULL);

    ASSERT_TRUE(res == 0);
}

TEST_F (MiddlewareSubscriptionTests, hasWildcards)
{
    int res = NULL;

    res = mBridge->bridgeMamaSubscriptionHasWildcards(NULL);

    ASSERT_TRUE(res == 0);
}

TEST_F (MiddlewareSubscriptionTests, getPlatformError)
{
    void* error = NOT_NULL;
    mama_status status = MAMA_STATUS_OK;
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ (MAMA_STATUS_OK,
    		   mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
    		                                                    tport, queue, callbacks,
    		                                                    parent, closure));

    status = mBridge->bridgeMamaSubscriptionGetPlatformError(subscriber, &error);

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));

    CHECK_NON_IMPLEMENTED_OPTIONAL(status);

    ASSERT_EQ(MAMA_STATUS_OK,
              status);
}

TEST_F (MiddlewareSubscriptionTests, getPlatformErrorInvalidError)
{
	mama_status status = mBridge->bridgeMamaSubscriptionGetPlatformError(subscriber,
                                                               NULL);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               status);
}

TEST_F (MiddlewareSubscriptionTests, getPlatformErrorInvalidSubBridge)
{
    void* error = NOT_NULL;
    mama_status status = mBridge->bridgeMamaSubscriptionGetPlatformError(NULL,
                                                               &error);
    CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               status);
}

TEST_F (MiddlewareSubscriptionTests, isTportDisconnectedInvalid)
{
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               mBridge->bridgeMamaSubscriptionIsTportDisconnected(NULL));
}

TEST_F (MiddlewareSubscriptionTests, setTopicClosure)
{
    void* newClosure = NOT_NULL;
    mama_status status = MAMA_STATUS_OK;
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));

    status = mBridge->bridgeMamaSubscriptionSetTopicClosure(subscriber,newClosure);

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));

    CHECK_NON_IMPLEMENTED_OPTIONAL(status);

    ASSERT_EQ (MAMA_STATUS_OK,
               status);
}

TEST_F (MiddlewareSubscriptionTests, setTopicClosureInvalidSubBridge)
{
    void* closure = NOT_NULL;
    mama_status status = mBridge->bridgeMamaSubscriptionSetTopicClosure(NULL,
                                                              closure);

    CHECK_NON_IMPLEMENTED_OPTIONAL(status);

    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               status);
}

TEST_F (MiddlewareSubscriptionTests, muteCurrentTopic)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));

    ASSERT_EQ (MAMA_STATUS_OK,
               mBridge->bridgeMamaSubscriptionMuteCurrentTopic(subscriber));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));
}

TEST_F (MiddlewareSubscriptionTests, muteCurrentTopicInvalid)
{
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               mBridge->bridgeMamaSubscriptionMuteCurrentTopic(NULL));
}

<commit_msg>UNITTEST: Fixed issue where MAMA queue destroy was attempted after close<commit_after>/* $Id: middlewareSubscriptionTests.cpp,v 1.1.2.5 2012/12/17 15:46:04 matthewmulhern Exp $
 *
 * OpenMAMA: The open middleware agnostic messaging API
 * Copyright (C) 2011 NYSE Technologies, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

#include <gtest/gtest.h>
#include "mama/mama.h"
#include "MainUnitTestC.h"
#include <iostream>
#include "bridge.h"
#include "mama/types.h"

using std::cout;
using std::endl;

static void onCreate (mamaSubscription subscription, void* closure);

static void onError(mamaSubscription subscription,
                    mama_status      status,
                    void*            platformError,
                    const char*      subject,
                    void*            closure);

static void onQuality(mamaSubscription subsc,
                      mamaQuality      quality,
                      const char*      symbol,
                      short            cause,
                      const void*      platformInfo,
                      void*            closure);

static void onMsg(mamaSubscription subscription,
                  mamaMsg          msg,
                  void*            closure,
                  void*            itemClosure);

static void onGap(mamaSubscription subsc, void* closure);
static void onRecapRequest(mamaSubscription subsc, void* closure);
static void onDestroy(mamaSubscription subsc, void* closure);

class MiddlewareSubscriptionTests : public ::testing::Test
{
protected:
    MiddlewareSubscriptionTests(void);
    virtual ~MiddlewareSubscriptionTests(void);

    virtual void SetUp(void);
    virtual void TearDown(void);

    mamaBridge mBridge;
    mamaTransport tport;
    const char*   tportName;

    subscriptionBridge subscriber;
    mamaSource         source;
    const char*        sourceName;
    const char*        symbol;
    mamaQueue          queue;
    void*              closure;
    mamaSubscription   parent;
    mamaMsgCallbacks   callbacks;
};

MiddlewareSubscriptionTests::MiddlewareSubscriptionTests(void)
    : tport (NULL),
      tportName ("test_tport"),
      source (NULL),
      sourceName ("src"),
      symbol ("SYM"),
      queue (NULL),
      closure (NULL)
{
    mama_loadBridge (&mBridge, getMiddleware());

    mamaQueue_create(&queue, mBridge);
}

MiddlewareSubscriptionTests::~MiddlewareSubscriptionTests(void)
{
}

void MiddlewareSubscriptionTests::SetUp(void)
{
    mama_open();  /* Forces loading of entitlements bridges as necessary */
    mamaTransport_allocate (&tport);
    mamaTransport_create   (tport, tportName, mBridge);

    mamaSource_create(&source);
    mamaSource_setId(source, "SRC");
    mamaSource_setTransport(source, tport);
    mamaSource_setSymbolNamespace(source, "NASDAQ");

    mamaSubscription_allocate(&parent);

    callbacks.onCreate          = onCreate;
    callbacks.onError           = onError;
    callbacks.onQuality         = onQuality;
    callbacks.onMsg             = onMsg;
    callbacks.onGap             = onGap;
    callbacks.onRecapRequest    = onRecapRequest;
    callbacks.onDestroy         = onDestroy;
}

void MiddlewareSubscriptionTests::TearDown(void)
{
    mamaTransport_destroy (tport);
    mamaSubscription_deallocate(parent);
    mamaQueue_destroy (queue);
    mama_close();
}

static void onCreate (mamaSubscription subscription,
                      void* closure)
{
}

static void onError(mamaSubscription subscription,
                    mama_status      status,
                    void*            platformError,
                    const char*      subject,
                    void*            closure)
{
}

static void onQuality(mamaSubscription subsc,
                      mamaQuality      quality,
                      const char*      symbol,
                      short            cause,
                      const void*      platformInfo,
                      void*            closure)
{
}

static void onMsg(mamaSubscription subscription,
                  mamaMsg          msg,
                  void*            closure,
                  void*            itemClosure)
{
}

static void onGap(mamaSubscription subsc, void* closure)
{
}

static void onRecapRequest(mamaSubscription subsc, void* closure)
{
}

static void onDestroy(mamaSubscription subsc, void* closure)
{
}

/*===================================================================
 =               mamaSubscription bridge functions                   =
 ====================================================================*/

/* TODO:
 * Discuss the validity of these tests - ultimately we double create
 * subscriptions, which I would assume isn't supposed to be expected behaviour.
 */
TEST_F (MiddlewareSubscriptionTests, DISABLED_createDestroy)
/* cores*/
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));

    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_destroy(parent));

    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_deallocate(parent));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidResult)
{
    ASSERT_EQ(MAMA_STATUS_NULL_ARG,
              mBridge->bridgeMamaSubscriptionCreate(NULL, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidTport)
{
    ASSERT_EQ(MAMA_STATUS_NULL_ARG,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    NULL, queue, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidSourceName)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, NULL, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidSymbol)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, NULL,
                                                    tport, queue, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidQueue)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, NULL, callbacks,
                                                    parent, closure));
}

TEST_F (MiddlewareSubscriptionTests, createInvalidParent)
{
    ASSERT_EQ(MAMA_STATUS_NULL_ARG,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    NULL, closure));
}
/* TEST COMMENTED OUT BECAUSE mamaMsgCallbacks CAN'T BE CAST AS NULL!
TEST_F (MiddlewareSubscriptionTests, createInvalidCallbacks)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, NULL,
                                                    parent, closure));
}
*/

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidResult)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(NULL, sourceName, symbol,
                                                            tport, queue, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidSource)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, NULL, symbol,
                                                            tport, queue, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidSymbol)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, NULL,
                                                            tport, queue, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidTport)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, symbol,
                                                            NULL, queue, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidQueue)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, symbol,
                                                            tport, NULL, callbacks,
                                                            parent, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
    		  status);
}

TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidParent)
{
	mama_status status = mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, symbol,
                                                            tport, queue, callbacks,
                                                            NULL, closure);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ(MAMA_STATUS_OK,
              status);
}
/* COMMENTED OUT BECAUSE mamaMsg Callbacks CAN'T BE CAST AS NULL
TEST_F (MiddlewareSubscriptionTests, createWildCardInvalidCallbacks)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreateWildCard(&subscriber, sourceName, symbol,
                                                            tport, queue, NULL,
                                                            parent, closure));
}
*/

TEST_F (MiddlewareSubscriptionTests, mute)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));

    ASSERT_EQ (MAMA_STATUS_OK,
               mBridge->bridgeMamaSubscriptionMute(subscriber));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));
}

TEST_F (MiddlewareSubscriptionTests, muteInvalid)
{
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               mBridge->bridgeMamaSubscriptionMute(NULL));
}

TEST_F (MiddlewareSubscriptionTests, destroyInvalid)
{
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               mBridge->bridgeMamaSubscriptionDestroy(NULL));
}

TEST_F (MiddlewareSubscriptionTests, isValid)
{
    int res = NULL;
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));

    res = mBridge->bridgeMamaSubscriptionIsValid(subscriber);
    ASSERT_TRUE(res != NULL);

}

TEST_F (MiddlewareSubscriptionTests, isValidInvalid)
{
    int res = NULL;

    res = mBridge->bridgeMamaSubscriptionIsValid(NULL);

    ASSERT_TRUE(res == 0);
}

TEST_F (MiddlewareSubscriptionTests, hasWildcards)
{
    int res = NULL;

    res = mBridge->bridgeMamaSubscriptionHasWildcards(NULL);

    ASSERT_TRUE(res == 0);
}

TEST_F (MiddlewareSubscriptionTests, getPlatformError)
{
    void* error = NOT_NULL;
    mama_status status = MAMA_STATUS_OK;
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ (MAMA_STATUS_OK,
    		   mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
    		                                                    tport, queue, callbacks,
    		                                                    parent, closure));

    status = mBridge->bridgeMamaSubscriptionGetPlatformError(subscriber, &error);

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));

    CHECK_NON_IMPLEMENTED_OPTIONAL(status);

    ASSERT_EQ(MAMA_STATUS_OK,
              status);
}

TEST_F (MiddlewareSubscriptionTests, getPlatformErrorInvalidError)
{
	mama_status status = mBridge->bridgeMamaSubscriptionGetPlatformError(subscriber,
                                                               NULL);
	CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               status);
}

TEST_F (MiddlewareSubscriptionTests, getPlatformErrorInvalidSubBridge)
{
    void* error = NOT_NULL;
    mama_status status = mBridge->bridgeMamaSubscriptionGetPlatformError(NULL,
                                                               &error);
    CHECK_NON_IMPLEMENTED_OPTIONAL(status);
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               status);
}

TEST_F (MiddlewareSubscriptionTests, isTportDisconnectedInvalid)
{
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               mBridge->bridgeMamaSubscriptionIsTportDisconnected(NULL));
}

TEST_F (MiddlewareSubscriptionTests, setTopicClosure)
{
    void* newClosure = NOT_NULL;
    mama_status status = MAMA_STATUS_OK;
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));

    status = mBridge->bridgeMamaSubscriptionSetTopicClosure(subscriber,newClosure);

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));

    CHECK_NON_IMPLEMENTED_OPTIONAL(status);

    ASSERT_EQ (MAMA_STATUS_OK,
               status);
}

TEST_F (MiddlewareSubscriptionTests, setTopicClosureInvalidSubBridge)
{
    void* closure = NOT_NULL;
    mama_status status = mBridge->bridgeMamaSubscriptionSetTopicClosure(NULL,
                                                              closure);

    CHECK_NON_IMPLEMENTED_OPTIONAL(status);

    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               status);
}

TEST_F (MiddlewareSubscriptionTests, muteCurrentTopic)
{
    ASSERT_EQ(MAMA_STATUS_OK,
              mamaSubscription_create(parent, queue, &callbacks, source, sourceName, closure));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionCreate(&subscriber, sourceName, symbol,
                                                    tport, queue, callbacks,
                                                    parent, closure));

    ASSERT_EQ (MAMA_STATUS_OK,
               mBridge->bridgeMamaSubscriptionMuteCurrentTopic(subscriber));

    ASSERT_EQ(MAMA_STATUS_OK,
              mBridge->bridgeMamaSubscriptionDestroy(subscriber));
}

TEST_F (MiddlewareSubscriptionTests, muteCurrentTopicInvalid)
{
    ASSERT_EQ (MAMA_STATUS_NULL_ARG,
               mBridge->bridgeMamaSubscriptionMuteCurrentTopic(NULL));
}

<|endoftext|>


<commit_before>#include "motor/car_motor_mapper.hpp"

#include <array>
#include <cstddef>
#include "protocol/messages.hpp"

CarMotorMapper::CarMotorMapper(PWMDeviceGroup<4>& motorDevices, PWMDeviceGroup<4>& servoDevices, Communicator& communicator)
  : motorDevices(motorDevices),
    servoDevices(servoDevices),
    throttleStream(communicator, 1) {
}

void CarMotorMapper::init() {
}

void CarMotorMapper::run(bool armed, actuator_setpoint_t& input) {
  // Motor speeds depend only on throttle input
  std::array<float, 4> motors {
    input.throttle_sp,   // front left
    input.throttle_sp,   // back left
    input.throttle_sp,   // back right
    input.throttle_sp    // front right
  };

  motorDevices.set(armed, motorOutputs);

  // Servos control yaw angle of the vehicle
  std::array<float, 4> servos {
    // TODO(kyle): signs
    -input.yaw_sp / 2,   // front left
    input.yaw_sp / 2,   // back left
    input.yaw_sp / 2,   // back right
    -input.yaw_sp / 2    // front right
  };

  servoDevices.set(armed, servoOutputs);

  if(throttleStream.ready()) {
    protocol::message::motor_throttle_message_t msg;

    for(std::size_t i = 0; i < 4; i++) {
      msg.throttles[i] = motorOutputs[i];
    }

    throttleStream.publish(msg);
  }
}
<commit_msg>Fix changed name.<commit_after>#include "motor/car_motor_mapper.hpp"

#include <array>
#include <cstddef>
#include "protocol/messages.hpp"

CarMotorMapper::CarMotorMapper(PWMDeviceGroup<4>& motorDevices, PWMDeviceGroup<4>& servoDevices, Communicator& communicator)
  : motorDevices(motorDevices),
    servoDevices(servoDevices),
    throttleStream(communicator, 1) {
}

void CarMotorMapper::init() {
}

void CarMotorMapper::run(bool armed, actuator_setpoint_t& input) {
  // Motor speeds depend only on throttle input
  std::array<float, 4> motors {
    input.throttle_sp,   // front left
    input.throttle_sp,   // back left
    input.throttle_sp,   // back right
    input.throttle_sp    // front right
  };

  motorDevices.set(armed, motors);

  // Servos control yaw angle of the vehicle
  std::array<float, 4> servos {
    // TODO(kyle): signs
    -input.yaw_sp / 2,   // front left
    input.yaw_sp / 2,   // back left
    input.yaw_sp / 2,   // back right
    -input.yaw_sp / 2    // front right
  };

  servoDevices.set(armed, servos);

  if(throttleStream.ready()) {
    protocol::message::motor_throttle_message_t msg;

    for(std::size_t i = 0; i < 4; i++) {
      msg.throttles[i] = motors[i];
    }

    throttleStream.publish(msg);
  }
}
<|endoftext|>


<commit_before>#include <sstream>
#include <string>
#include <boost/lexical_cast.hpp>
#include "asioWrapper.h"

namespace twitpp {
namespace asioWrapper {

namespace asio = boost::asio;

Client::Client(asio::io_service& io_service, asio::ssl::context& context, const std::string& host, const std::string& path)
    : resolver_(io_service), socket_(io_service, context), host_(host), path_(path) {}

// GET method
void Client::get(const std::string& header, std::function<void(std::string&)> handler) {
  handler_ = handler;

  // create request;
  std::ostream request_stream(&request_buffer_);
  request_stream << "GET " << path_ << " HTTP/1.1\r\n";
  request_stream << "Host: " << host_ << "\r\n";
  request_stream << "Accept: */*\r\n";
  if (!header.empty()) {
    request_stream << header << "\r\n";
  }
  request_stream << "Connection: close\r\n\r\n";

  // get server name and host info
  asio::ip::tcp::resolver::query query(host_, "443");
  resolver_.async_resolve(query,
                          boost::bind(&Client::handleResolve, this, asio::placeholders::error, asio::placeholders::iterator));
}

// POST method
void Client::post(const std::string& header, const std::string& data, std::function<void(std::string&)> handler) {
  handler_ = handler;

  // create request;
  std::ostream request_stream(&request_buffer_);
  request_stream << "POST " << path_ << " HTTP/1.1\r\n";
  request_stream << "Host: " << host_ << "\r\n";
  request_stream << "Accept: */*\r\n";
  if (!header.empty()) {
    request_stream << header << "\r\n";
  }
  if (!data.empty()) {
    request_stream << "Content-Length: " << data.length() << "\r\n";
    request_stream << "Content-Type: application/x-www-form-urlencoded\r\n";
    request_stream << "Connection: close\r\n\r\n";
    request_stream << data << "\r\n";
  } else {
    request_stream << "Connection: close\r\n\r\n";
  }

  // get server name and host info
  asio::ip::tcp::resolver::query query(host_, "443");
  resolver_.async_resolve(query,
                          boost::bind(&Client::handleResolve, this, asio::placeholders::error, asio::placeholders::iterator));
}

void Client::handleResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpoint_iterator) {
  if (!error) {
    asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
                        boost::bind(&Client::handleConnect, this, asio::placeholders::error));
  } else {
    std::cout << "Error: " << error.message() << "\n";
  }
}

void Client::handleConnect(const boost::system::error_code& error) {
  if (!error) {
    socket_.async_handshake(asio::ssl::stream_base::client,
                            boost::bind(&Client::handleHandshake, this, asio::placeholders::error));
  } else {
    std::cout << "Connect failed: " << error.message() << "\n";
  }
}

void Client::handleHandshake(const boost::system::error_code& error) {
  if (!error) {
    asio::async_write(socket_, request_buffer_, boost::bind(&Client::handleWrite, this, asio::placeholders::error));
  } else {
    std::cout << "Handshake failed: " << error.message() << "\n";
  }
}

void Client::handleWrite(const boost::system::error_code& error) {
  if (!error) {
    asio::async_read_until(socket_, response_buffer_, "\r\n",
                           boost::bind(&Client::handleReadStatus, this, asio::placeholders::error));
  } else {
    std::cout << "Write failed: " << error.message() << "\n";
  }
}

void Client::handleReadStatus(const boost::system::error_code& error) {
  if (!error) {
    // check response
    std::istream responseStream(&response_buffer_);
    responseStream >> response_.http_version;
    responseStream >> response_.status_code;
    std::getline(responseStream, response_.status_message);

    if (!responseStream || response_.http_version.substr(0, 5) != "HTTP/") {
      std::cout << "Invalid response\n";
      return;
    }

    // read response header
    asio::async_read_until(socket_, response_buffer_, "\r\n\r\n",
                           boost::bind(&Client::handleReadHeader, this, asio::placeholders::error));
  } else {
    std::cout << "Read failed: " << error.message() << "\n";
  }
}

void Client::handleReadHeader(const boost::system::error_code& error) {
  if (!error) {
    // read response header
    std::istream responseStream(&response_buffer_);
    std::string header;
    while (std::getline(responseStream, header) && header != "\r") {
      std::string field_name(header, 0, header.find(":", 0));
      std::string field_body(header, header.find(":", 0) + 2);

      response_.response_header[field_name] = field_body;
    }

    if (response_.response_header.count("transfer-encoding") != 0 ||
        response_.response_header["transfer-encoding"] == "chunked") {
      // chuncked transfer
      asio::async_read_until(socket_, response_buffer_, "\r\n",
                             boost::bind(&Client::handleReadChunkSize, this, asio::placeholders::error));
    } else if (response_.response_header.count("Content-Length") != 0) {
      // use content length
      std::size_t content_length = std::stoi(response_.response_header["Content-Length"]);

      asio::async_read(socket_, response_buffer_,
                       asio::transfer_at_least(content_length - asio::buffer_size(response_buffer_.data())),
                       boost::bind(&Client::handleReadContent, this, content_length, asio::placeholders::error));
    } else if (response_.response_header.count("content-length") != 0) {
      std::size_t content_length = std::stoi(response_.response_header["content-length"]);

      asio::async_read(socket_, response_buffer_,
                       asio::transfer_at_least(content_length - asio::buffer_size(response_buffer_.data())),
                       boost::bind(&Client::handleReadContent, this, content_length, asio::placeholders::error));
    } else {
      // other (not working now
      asio::async_read(socket_, response_buffer_, asio::transfer_all(),
                       boost::bind(&Client::handleReadContentAll, this, asio::placeholders::error));
    }

  } else {
    std::cout << "Error: " << error.message() << "\n";
  }
}

void Client::handleReadChunkSize(const boost::system::error_code& error) {
  if (!error) {
    if (response_buffer_.size() == 0) {
      return;
    } else if (response_buffer_.size() <= 2) {
      asio::async_read_until(socket_, response_buffer_, "\r\n",
                             boost::bind(&Client::handleReadChunkSize, this, asio::placeholders::error));
    } else {
      // read chunk size
      boost::system::error_code ec;
      asio::read_until(socket_, response_buffer_, "\r\n", ec);
      std::size_t chunk;
      response_buffer_.consume(chunk_parser((std::string)asio::buffer_cast<const char*>(response_buffer_.data()), chunk));

      asio::async_read(socket_, response_buffer_, asio::transfer_at_least(chunk - asio::buffer_size(response_buffer_.data())),
                       boost::bind(&Client::handleReadChunkBody, this, chunk, asio::placeholders::error));
    }
  } else if (error != asio::error::eof) {
    std::cout << "Error: " << error.message() << "\n";
  }
}

void Client::handleReadChunkBody(std::size_t content_length, const boost::system::error_code& error) {
  if (!error) {
    boost::system::error_code ec;
    asio::read(socket_, response_buffer_,
               asio::transfer_at_least((content_length + 2) - asio::buffer_size(response_buffer_.data())), ec);

    response_.response_body.append(boost::asio::buffer_cast<const char*>(response_buffer_.data()), content_length);
    response_buffer_.consume(content_length + 2);
    handler_(response_.response_body);

    asio::async_read_until(socket_, response_buffer_, "\r\n",
                           boost::bind(&Client::handleReadChunkSize, this, asio::placeholders::error));
  } else if (error != asio::error::eof) {
    std::cout << "Error: " << error.message() << "\n";
  }
}

void Client::handleReadContent(std::size_t content_length, const boost::system::error_code& error) {
  if (!error) {
    if (response_buffer_.size() == 0) {
      std::cout << "ERROR" << std::endl;
    }

    response_.response_body.append(asio::buffers_begin(response_buffer_.data()), asio::buffers_end(response_buffer_.data()));
    response_buffer_.consume(response_buffer_.size());
    handler_(response_.response_body);
  } else if (error != asio::error::eof) {
    std::cout << "Error: " << error.message() << "\n";
  }
}

void Client::handleReadContentAll(const boost::system::error_code& error) {
  if (!error) {
    std::ostringstream tmp;
    tmp << &response_buffer_;
    response_.response_body = tmp.str();
    handler_(response_.response_body);

    // Continue reading remaining data until EOF.
    asio::async_read(socket_, response_buffer_, asio::transfer_at_least(1),
                     boost::bind(&Client::handleReadContentAll, this, asio::placeholders::error));
  } else if (error != asio::error::eof) {
    std::cout << "Error: " << error.message() << "\n";
  }
}

}
}
<commit_msg>change error massage<commit_after>#include <sstream>
#include <string>
#include <boost/lexical_cast.hpp>
#include "asioWrapper.h"

namespace twitpp {
namespace asioWrapper {

namespace asio = boost::asio;

Client::Client(asio::io_service& io_service, asio::ssl::context& context, const std::string& host, const std::string& path)
    : resolver_(io_service), socket_(io_service, context), host_(host), path_(path) {}

// GET method
void Client::get(const std::string& header, std::function<void(std::string&)> handler) {
  handler_ = handler;

  // create request;
  std::ostream request_stream(&request_buffer_);
  request_stream << "GET " << path_ << " HTTP/1.1\r\n";
  request_stream << "Host: " << host_ << "\r\n";
  request_stream << "Accept: */*\r\n";
  if (!header.empty()) {
    request_stream << header << "\r\n";
  }
  request_stream << "Connection: close\r\n\r\n";

  // get server name and host info
  asio::ip::tcp::resolver::query query(host_, "443");
  resolver_.async_resolve(query,
                          boost::bind(&Client::handleResolve, this, asio::placeholders::error, asio::placeholders::iterator));
}

// POST method
void Client::post(const std::string& header, const std::string& data, std::function<void(std::string&)> handler) {
  handler_ = handler;

  // create request;
  std::ostream request_stream(&request_buffer_);
  request_stream << "POST " << path_ << " HTTP/1.1\r\n";
  request_stream << "Host: " << host_ << "\r\n";
  request_stream << "Accept: */*\r\n";
  if (!header.empty()) {
    request_stream << header << "\r\n";
  }
  if (!data.empty()) {
    request_stream << "Content-Length: " << data.length() << "\r\n";
    request_stream << "Content-Type: application/x-www-form-urlencoded\r\n";
    request_stream << "Connection: close\r\n\r\n";
    request_stream << data << "\r\n";
  } else {
    request_stream << "Connection: close\r\n\r\n";
  }

  // get server name and host info
  asio::ip::tcp::resolver::query query(host_, "443");
  resolver_.async_resolve(query,
                          boost::bind(&Client::handleResolve, this, asio::placeholders::error, asio::placeholders::iterator));
}

void Client::handleResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpoint_iterator) {
  if (!error) {
    asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
                        boost::bind(&Client::handleConnect, this, asio::placeholders::error));
  } else {
    std::cout << "Resolve failed: " << error.value() << "\n";
  }
}

void Client::handleConnect(const boost::system::error_code& error) {
  if (!error) {
    socket_.async_handshake(asio::ssl::stream_base::client,
                            boost::bind(&Client::handleHandshake, this, asio::placeholders::error));
  } else {
    std::cout << "Connect failed: " << error.value() << "\n";
  }
}

void Client::handleHandshake(const boost::system::error_code& error) {
  if (!error) {
    asio::async_write(socket_, request_buffer_, boost::bind(&Client::handleWrite, this, asio::placeholders::error));
  } else {
    std::cout << "Handshake failed: " << error.value()<< "\n";
  }
}

void Client::handleWrite(const boost::system::error_code& error) {
  if (!error) {
    asio::async_read_until(socket_, response_buffer_, "\r\n",
                           boost::bind(&Client::handleReadStatus, this, asio::placeholders::error));
  } else {
    std::cout << "Write failed: " << error.value() << "\n";
  }
}

void Client::handleReadStatus(const boost::system::error_code& error) {
  if (!error) {
    // check response
    std::istream responseStream(&response_buffer_);
    responseStream >> response_.http_version;
    responseStream >> response_.status_code;
    std::getline(responseStream, response_.status_message);

    if (!responseStream || response_.http_version.substr(0, 5) != "HTTP/") {
      std::cout << "Invalid response\n";
      return;
    }

    // read response header
    asio::async_read_until(socket_, response_buffer_, "\r\n\r\n",
                           boost::bind(&Client::handleReadHeader, this, asio::placeholders::error));
  } else {
    std::cout << "Read status failed: " << error.value() << "\n";
  }
}

void Client::handleReadHeader(const boost::system::error_code& error) {
  if (!error) {
    // read response header
    std::istream responseStream(&response_buffer_);
    std::string header;
    while (std::getline(responseStream, header) && header != "\r") {
      std::string field_name(header, 0, header.find(":", 0));
      std::string field_body(header, header.find(":", 0) + 2);

      response_.response_header[field_name] = field_body;
    }

    if (response_.response_header.count("transfer-encoding") != 0 ||
        response_.response_header["transfer-encoding"] == "chunked") {
      // chuncked transfer
      asio::async_read_until(socket_, response_buffer_, "\r\n",
                             boost::bind(&Client::handleReadChunkSize, this, asio::placeholders::error));
    } else if (response_.response_header.count("Content-Length") != 0) {
      // use content length
      std::size_t content_length = std::stoi(response_.response_header["Content-Length"]);

      asio::async_read(socket_, response_buffer_,
                       asio::transfer_at_least(content_length - asio::buffer_size(response_buffer_.data())),
                       boost::bind(&Client::handleReadContent, this, content_length, asio::placeholders::error));
    } else if (response_.response_header.count("content-length") != 0) {
      std::size_t content_length = std::stoi(response_.response_header["content-length"]);

      asio::async_read(socket_, response_buffer_,
                       asio::transfer_at_least(content_length - asio::buffer_size(response_buffer_.data())),
                       boost::bind(&Client::handleReadContent, this, content_length, asio::placeholders::error));
    } else {
      // other (not working now
      asio::async_read(socket_, response_buffer_, asio::transfer_all(),
                       boost::bind(&Client::handleReadContentAll, this, asio::placeholders::error));
    }

  } else {
    std::cout << "Read header failed: " << error.value() << "\n";
  }
}

void Client::handleReadChunkSize(const boost::system::error_code& error) {
  if (!error) {
    if (response_buffer_.size() == 0) {
      return;
    } else if (response_buffer_.size() <= 2) {
      asio::async_read_until(socket_, response_buffer_, "\r\n",
                             boost::bind(&Client::handleReadChunkSize, this, asio::placeholders::error));
    } else {
      // read chunk size
      boost::system::error_code ec;
      asio::read_until(socket_, response_buffer_, "\r\n", ec);
      std::size_t chunk;
      response_buffer_.consume(chunk_parser((std::string)asio::buffer_cast<const char*>(response_buffer_.data()), chunk));

      asio::async_read(socket_, response_buffer_, asio::transfer_at_least(chunk - asio::buffer_size(response_buffer_.data())),
                       boost::bind(&Client::handleReadChunkBody, this, chunk, asio::placeholders::error));
    }
  } else if (error != asio::error::eof) {
    std::cout << "Read chunksize failed: " << error.value() << "\n";
  }
}

void Client::handleReadChunkBody(std::size_t content_length, const boost::system::error_code& error) {
  if (!error) {
    boost::system::error_code ec;
    asio::read(socket_, response_buffer_,
               asio::transfer_at_least((content_length + 2) - asio::buffer_size(response_buffer_.data())), ec);

    response_.response_body.append(boost::asio::buffer_cast<const char*>(response_buffer_.data()), content_length);
    response_buffer_.consume(content_length + 2);
    handler_(response_.response_body);

    asio::async_read_until(socket_, response_buffer_, "\r\n",
                           boost::bind(&Client::handleReadChunkSize, this, asio::placeholders::error));
  } else if (error != asio::error::eof) {
    std::cout << "Read chunk failed: " << error.value() << "\n";
  }
}

void Client::handleReadContent(std::size_t content_length, const boost::system::error_code& error) {
  if (!error) {
    response_.response_body.append(asio::buffers_begin(response_buffer_.data()), asio::buffers_end(response_buffer_.data()));
    response_buffer_.consume(response_buffer_.size());
    handler_(response_.response_body);
  } else if (error != asio::error::eof) {
    std::cout << "Read content failed: " << error.value() << "\n";
  }
}

void Client::handleReadContentAll(const boost::system::error_code& error) {
  if (!error) {
    std::ostringstream tmp;
    tmp << &response_buffer_;
    response_.response_body = tmp.str();
    handler_(response_.response_body);

    // Continue reading remaining data until EOF.
    asio::async_read(socket_, response_buffer_, asio::transfer_at_least(1),
                     boost::bind(&Client::handleReadContentAll, this, asio::placeholders::error));
  } else if (error != asio::error::eof) {
    std::cout << "Read content all failed: " << error.value() << "\n";
  }
}

}
}
<|endoftext|>


<commit_before>#include "mugen_background.h"

#include <math.h>
#include <ostream>
#include <cstring>
#include <string>
#include <algorithm>
#include "globals.h"
#include "mugen_sprite.h"
#include "util/bitmap.h"

//static double pi = 3.14159265;

using namespace std;

static double interpolate(double f1, double f2, double p){
    return (f1 * (1.0 - p)) + (f2 * p);
}

struct Tile {
    int start;
    int total;
};

static Tile getTileData( int location, int length, int spacing, int total ){
    Tile tile;
    if (total == 0){
	tile.start = location;
	tile.total = 1;
	return tile;
    } else if (total > 1){
	tile.start = location;
	tile.total = total;
	return tile;
    } else if (total == 1){
	// Infinite tiling.. just tile on the board
	if (location < 0){
	    // Less than the board itself lets get location up to that point
	    while (location < 0){
		location+=spacing;
	    }
	    // Now backup 1 so we get the wrap effect
	    location-=spacing;
	} else{
	    // Either Larger than the board or inside seek back to beginning
	    while (location > 0){
		location-=spacing;
	    }
	}
	// Now figure out how many we need to do
	int temp = location;
	// Reuse total
	total = 0;
	while (temp < length){
	    total++;
	    temp+=spacing;
	}
	// Blammo
	tile.start = location;
	tile.total = total;
	return tile;
    }
    tile.start = 0;
    tile.total = 0;
    return tile;
}

static void doParallax(Bitmap &bmp, Bitmap &work, int leftx, int lefty, int xoffset, double top, double bot, int yscalestart, double yscaledelta, double yoffset, bool mask){
    const int height = bmp.getHeight();
    const int w = bmp.getWidth();
    int movex = 0;
    //double z = 1.0 / z1;
    //const double z_add = ((1.0 / z2) - z) / (y2 - y1);

    Global::debug(3) << "background leftx " << leftx << endl;

    for (int localy = 0; localy < height; ++localy ){
	//int width = bmp.getWidth()*z;
        const double range = (double)localy / (double)height;
	const double scale = interpolate(top, bot, range) - top;
	//const double newHeight = height*((yscalestart+(yoffset*yscaledelta))/100);
	//const double yscale = (newHeight/height);
	movex = (int)(leftx + (leftx - xoffset) * scale);
	bmp.Stretch(work, 0, localy, w, 1,movex, lefty+localy, w,1);
	//z +=  z_add;
	//Global::debug(1) << "Height: " << height << " | yscalestart: " << yscalestart << " | yscaledelta: " << yscaledelta << " | yoffset: " << yoffset << " | New Height: " << newHeight << " | yscale: " << yscale << endl;
    }
}

// mugen background
MugenBackground::MugenBackground( const unsigned long int &ticker ):
type(Normal),
groupNumber(-1),
imageNumber(-1),
actionno(-1),
id(0),
layerno(0),
startx(0),
starty(0),
deltax(1),
deltay(1),
trans(None),
alphalow(0),
alphahigh(0),
mask(false),
tilex(0),
tiley(0),
tilespacingx(0),
tilespacingy(0),
windowdeltax(0),
windowdeltay(0),
xscaletop(0),
xscalebot(0),
yscalestart(100),
yscaledelta(100),
positionlink(false),
velocityx(0),
velocityy(0),
sinx_amp(0),
sinx_period(0),
sinx_offset(0),
sinx_angle(0),
siny_amp(0),
siny_period(0),
siny_offset(0),
siny_angle(0),
xoffset(0),
yoffset(0),
movex(0),
movey(0),
velx(0),
vely(0),
stageTicker( ticker ),
x(0),
y(0),
visible(true),
enabled(true),
controller_offsetx(0),
controller_offsety(0),
sprite(0),
spriteBmp(0),
action(0),
linked(0),
runLink(false){
}
MugenBackground::MugenBackground( const MugenBackground &copy ):
stageTicker( copy.stageTicker ){
}
MugenBackground::~MugenBackground(){
    // Kill the bmp
    if( spriteBmp )delete spriteBmp;
}
MugenBackground & MugenBackground::operator=( const MugenBackground &copy ){

    return *this;
}

void MugenBackground::logic( const double x, const double y, const double placementx, const double placementy ){
    if (enabled){
	movex = movey = 0;
	movex += x * deltax;
	movey += y * deltay;
	velx += velocityx;
	vely += velocityy;
	/* how much should sin_angle be incremented by each frame?
	* I think the total angle should be (ticks % sin_period) * 2pi / sin_period
	* M (decimal) is the magnitude in pixels (amp)
	* P (decimal) is the period in game ticks (period)
	* O (decimal) is the time offset in game ticks (offset)
	* From updates.txt:  M * sine ((ticks+O)/P * 2 * Pi)
	* sinx_amp * sin((stageTicker+sinx_offset)/sinx_period * 2 * pi)) ? useless it seems
	*/
	//sin_angle += 0.00005;
	sinx_angle += 0.00005;
	siny_angle += 0.00005;

	if( type == Anim ) action->logic();

	this->x = (int)(placementx + xoffset + movex + velx + controller_offsetx + sinx_amp * sin(sinx_angle*sinx_period + sinx_offset));
	this->y = (int)(placementy + yoffset + movey + vely + controller_offsety + siny_amp * sin(siny_angle*siny_period + siny_offset));
    }
}

void MugenBackground::render( const int totalLength, const int totalHeight, Bitmap *work ){
    if (visible){
	switch( type ){
	    case Normal:{
		// Normal is a sprite
		// Tile it
		const int addw = spriteBmp->getWidth() + tilespacingx;
		const int addh = spriteBmp->getHeight() + tilespacingy;
		Tile tilev = getTileData(y, totalHeight, addh, tiley);
		for (int v = 0; v < tilev.total; ++v){
		    Tile tileh = getTileData(x, totalLength, addw, tilex);
		    for (int h = 0; h < tileh.total; ++h){
			draw( tileh.start, tilev.start, *work);
			tileh.start+=addw;
		    }
		    tilev.start+=addh;
		}
		break;
	    }
	    case Parallax:{
		// This is also a sprite but we must parallax it across the top and bottom to give the illusion of depth
		doParallax( *spriteBmp, *work, x, y, xoffset+((totalLength)/2), xscaletop, xscalebot, yscalestart, yscaledelta, (movey-deltay), mask);
		break;
	    }
	    case Anim:{
		// there is no sprite use our action!
		// Tiling action
		const int addw = tilespacingx;
		const int addh = tilespacingy;
		Tile tilev = getTileData(y, totalHeight, addh, tiley);
		for (int v = 0; v < tilev.total; ++v){
		    Tile tileh = getTileData(x, totalLength, addw, tilex);
		    for (int h = 0; h < tileh.total; ++h){
			action->render( tileh.start, tilev.start, *work);
			tileh.start+=addw;
		    }
		    tilev.start+=addh;
		}
		break;
	    }
	    case Dummy:
		// Do nothing
	    default:
		break;
	}
    }
}

void MugenBackground::preload( const int xaxis, const int yaxis ){
    // Do positionlink crap
    if (positionlink && !runLink){
	if (linked){
	    linked->setPositionLink(this);
	}
	runLink = true;
    }

    if (sprite){
	// Lets load our sprite
	Global::debug(1) << "Name: " << name << " | Mask: " << mask << endl;
	spriteBmp = new Bitmap(Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength, mask));
#if 0
	if (!mask){
	    // Restore color in case
	    int colors = 256;
	    int maskR = (int)sprite->pcx[sprite->newlength - colors*3 + 0];
	    int maskG = (int)sprite->pcx[sprite->newlength - colors*3 + 1];
	    int maskB = (int)sprite->pcx[sprite->newlength - colors*3 + 2];
	    int mask = Bitmap::makeColor(maskR, maskG, maskB);
	    for( int i = 0; i < spriteBmp->getHeight(); ++i ){
                for( int j = 0; j < spriteBmp->getWidth(); ++j ){
                    /* use getPixel/putPixel? */
                    int pix = spriteBmp->getPixel(j,i);
                    if (pix == Bitmap::MaskColor){
                        spriteBmp->putPixel(j,i, mask);
                    }
                }
            }
	}
#endif

	// Set our initial offsets
	xoffset = (xaxis - sprite->x) + startx;
	yoffset = (yaxis - sprite->y) + starty;
	velx = vely = 0;
	Global::debug(1) << "Using sprite. Name: " << name << " | X: " << sprite->x << " | Y: " << sprite->y << endl;
    } else {
	// Set our initial offsets
	xoffset = (xaxis) + startx;
	yoffset = (yaxis) + starty;
	velx = vely = 0;
    }
}

void MugenBackground::draw( const int ourx, const int oury, Bitmap &work ){
    // This needs to be a switch trans = None, Add, Add1, Sub1, Addalpha
    switch( trans ){
	case Addalpha:{
	    // Need to figure out blend correctly addalpha is given to two locations low and high ?
	    Bitmap::transBlender( 255, 255, 255, alphalow );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Add:{
	    // this additive 100% I assume... not totally sure
	    Bitmap::addBlender( 255, 255, 255, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Add1:{
	    // 50%
	    Bitmap::addBlender( 128, 128, 128, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Sub:{
	    // Shadow effect
	    Bitmap::differenceBlender( 128, 128, 128, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case None:
	default:{
	    if( mask )spriteBmp->draw( ourx,oury, work );
	    else spriteBmp->Blit( ourx, oury, work );
	    break;
	}
    }
}

    // Lets do our positionlink stuff
void MugenBackground::setPositionLink(MugenBackground *bg){
    if (positionlink){
	if (linked){
	    linked->setPositionLink(bg);
	    return;
	}
    }
    bg->startx += startx;
    bg->starty += starty;
    bg->deltax = deltax;
    bg->deltay = deltay;
    bg->sinx_amp = sinx_amp;
    bg->sinx_offset = sinx_offset;
    bg->sinx_period = sinx_period;
    bg->siny_amp = siny_amp;
    bg->siny_offset = siny_offset;
    bg->siny_period = siny_period;
    bg->velocityx = velocityx;
    bg->velocityy = velocityy;

    //Global::debug(1) << "Positionlinked bg: " << bg->name << " set to x: " << bg->startx << " y: " << bg->starty << endl;
}

<commit_msg>Corrected possible memory leak, removed old code<commit_after>#include "mugen_background.h"

#include <math.h>
#include <ostream>
#include <cstring>
#include <string>
#include <algorithm>
#include "globals.h"
#include "mugen_sprite.h"
#include "util/bitmap.h"

//static double pi = 3.14159265;

using namespace std;

static double interpolate(double f1, double f2, double p){
    return (f1 * (1.0 - p)) + (f2 * p);
}

struct Tile {
    int start;
    int total;
};

static Tile getTileData( int location, int length, int spacing, int total ){
    Tile tile;
    if (total == 0){
	tile.start = location;
	tile.total = 1;
	return tile;
    } else if (total > 1){
	tile.start = location;
	tile.total = total;
	return tile;
    } else if (total == 1){
	// Infinite tiling.. just tile on the board
	if (location < 0){
	    // Less than the board itself lets get location up to that point
	    while (location < 0){
		location+=spacing;
	    }
	    // Now backup 1 so we get the wrap effect
	    location-=spacing;
	} else{
	    // Either Larger than the board or inside seek back to beginning
	    while (location > 0){
		location-=spacing;
	    }
	}
	// Now figure out how many we need to do
	int temp = location;
	// Reuse total
	total = 0;
	while (temp < length){
	    total++;
	    temp+=spacing;
	}
	// Blammo
	tile.start = location;
	tile.total = total;
	return tile;
    }
    tile.start = 0;
    tile.total = 0;
    return tile;
}

static void doParallax(Bitmap &bmp, Bitmap &work, int leftx, int lefty, int xoffset, double top, double bot, int yscalestart, double yscaledelta, double yoffset, bool mask){
    const int height = bmp.getHeight();
    const int w = bmp.getWidth();
    int movex = 0;
    //double z = 1.0 / z1;
    //const double z_add = ((1.0 / z2) - z) / (y2 - y1);

    Global::debug(3) << "background leftx " << leftx << endl;

    for (int localy = 0; localy < height; ++localy ){
	//int width = bmp.getWidth()*z;
        const double range = (double)localy / (double)height;
	const double scale = interpolate(top, bot, range) - top;
	//const double newHeight = height*((yscalestart+(yoffset*yscaledelta))/100);
	//const double yscale = (newHeight/height);
	movex = (int)(leftx + (leftx - xoffset) * scale);
	bmp.Stretch(work, 0, localy, w, 1,movex, lefty+localy, w,1);
	//z +=  z_add;
	//Global::debug(1) << "Height: " << height << " | yscalestart: " << yscalestart << " | yscaledelta: " << yscaledelta << " | yoffset: " << yoffset << " | New Height: " << newHeight << " | yscale: " << yscale << endl;
    }
}

// mugen background
MugenBackground::MugenBackground( const unsigned long int &ticker ):
type(Normal),
groupNumber(-1),
imageNumber(-1),
actionno(-1),
id(0),
layerno(0),
startx(0),
starty(0),
deltax(1),
deltay(1),
trans(None),
alphalow(0),
alphahigh(0),
mask(false),
tilex(0),
tiley(0),
tilespacingx(0),
tilespacingy(0),
windowdeltax(0),
windowdeltay(0),
xscaletop(0),
xscalebot(0),
yscalestart(100),
yscaledelta(100),
positionlink(false),
velocityx(0),
velocityy(0),
sinx_amp(0),
sinx_period(0),
sinx_offset(0),
sinx_angle(0),
siny_amp(0),
siny_period(0),
siny_offset(0),
siny_angle(0),
xoffset(0),
yoffset(0),
movex(0),
movey(0),
velx(0),
vely(0),
stageTicker( ticker ),
x(0),
y(0),
visible(true),
enabled(true),
controller_offsetx(0),
controller_offsety(0),
sprite(0),
spriteBmp(0),
action(0),
linked(0),
runLink(false){
}
MugenBackground::MugenBackground( const MugenBackground &copy ):
stageTicker( copy.stageTicker ){
}
MugenBackground::~MugenBackground(){
    // Kill the bmp
    if( spriteBmp )delete spriteBmp;
}
MugenBackground & MugenBackground::operator=( const MugenBackground &copy ){

    return *this;
}

void MugenBackground::logic( const double x, const double y, const double placementx, const double placementy ){
    if (enabled){
	movex = movey = 0;
	movex += x * deltax;
	movey += y * deltay;
	velx += velocityx;
	vely += velocityy;
	/* how much should sin_angle be incremented by each frame?
	* I think the total angle should be (ticks % sin_period) * 2pi / sin_period
	* M (decimal) is the magnitude in pixels (amp)
	* P (decimal) is the period in game ticks (period)
	* O (decimal) is the time offset in game ticks (offset)
	* From updates.txt:  M * sine ((ticks+O)/P * 2 * Pi)
	* sinx_amp * sin((stageTicker+sinx_offset)/sinx_period * 2 * pi)) ? useless it seems
	*/
	//sin_angle += 0.00005;
	sinx_angle += 0.00005;
	siny_angle += 0.00005;

	if( type == Anim ) action->logic();

	this->x = (int)(placementx + xoffset + movex + velx + controller_offsetx + sinx_amp * sin(sinx_angle*sinx_period + sinx_offset));
	this->y = (int)(placementy + yoffset + movey + vely + controller_offsety + siny_amp * sin(siny_angle*siny_period + siny_offset));
    }
}

void MugenBackground::render( const int totalLength, const int totalHeight, Bitmap *work ){
    if (visible){
	switch( type ){
	    case Normal:{
		// Normal is a sprite
		// Tile it
		const int addw = spriteBmp->getWidth() + tilespacingx;
		const int addh = spriteBmp->getHeight() + tilespacingy;
		Tile tilev = getTileData(y, totalHeight, addh, tiley);
		for (int v = 0; v < tilev.total; ++v){
		    Tile tileh = getTileData(x, totalLength, addw, tilex);
		    for (int h = 0; h < tileh.total; ++h){
			draw( tileh.start, tilev.start, *work);
			tileh.start+=addw;
		    }
		    tilev.start+=addh;
		}
		break;
	    }
	    case Parallax:{
		// This is also a sprite but we must parallax it across the top and bottom to give the illusion of depth
		doParallax( *spriteBmp, *work, x, y, xoffset+((totalLength)/2), xscaletop, xscalebot, yscalestart, yscaledelta, (movey-deltay), mask);
		break;
	    }
	    case Anim:{
		// there is no sprite use our action!
		// Tiling action
		const int addw = tilespacingx;
		const int addh = tilespacingy;
		Tile tilev = getTileData(y, totalHeight, addh, tiley);
		for (int v = 0; v < tilev.total; ++v){
		    Tile tileh = getTileData(x, totalLength, addw, tilex);
		    for (int h = 0; h < tileh.total; ++h){
			action->render( tileh.start, tilev.start, *work);
			tileh.start+=addw;
		    }
		    tilev.start+=addh;
		}
		break;
	    }
	    case Dummy:
		// Do nothing
	    default:
		break;
	}
    }
}

void MugenBackground::preload( const int xaxis, const int yaxis ){
    // Do positionlink crap
    if (positionlink && !runLink){
	if (linked){
	    linked->setPositionLink(this);
	}
	runLink = true;
    }

    if (sprite){
	// Lets load our sprite
	Global::debug(1) << "Name: " << name << " | Mask: " << mask << endl;
	if( spriteBmp == 0 ){
	    spriteBmp = new Bitmap(Bitmap::memoryPCX((unsigned char*) sprite->pcx, sprite->newlength, mask));
	}
	// Set our initial offsets
	xoffset = (xaxis - sprite->x) + startx;
	yoffset = (yaxis - sprite->y) + starty;
	velx = vely = 0;
	Global::debug(1) << "Using sprite. Name: " << name << " | X: " << sprite->x << " | Y: " << sprite->y << endl;
    } else {
	// Set our initial offsets
	xoffset = (xaxis) + startx;
	yoffset = (yaxis) + starty;
	velx = vely = 0;
    }
}

void MugenBackground::draw( const int ourx, const int oury, Bitmap &work ){
    // This needs to be a switch trans = None, Add, Add1, Sub1, Addalpha
    switch( trans ){
	case Addalpha:{
	    // Need to figure out blend correctly addalpha is given to two locations low and high ?
	    Bitmap::transBlender( 255, 255, 255, alphalow );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Add:{
	    // this additive 100% I assume... not totally sure
	    Bitmap::addBlender( 255, 255, 255, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Add1:{
	    // 50%
	    Bitmap::addBlender( 128, 128, 128, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case Sub:{
	    // Shadow effect
	    Bitmap::differenceBlender( 128, 128, 128, 255 );
	    spriteBmp->drawTrans( ourx, oury, work);
	    break;
	}
	case None:
	default:{
	    if( mask )spriteBmp->draw( ourx,oury, work );
	    else spriteBmp->Blit( ourx, oury, work );
	    break;
	}
    }
}

    // Lets do our positionlink stuff
void MugenBackground::setPositionLink(MugenBackground *bg){
    if (positionlink){
	if (linked){
	    linked->setPositionLink(bg);
	    return;
	}
    }
    bg->startx += startx;
    bg->starty += starty;
    bg->deltax = deltax;
    bg->deltay = deltay;
    bg->sinx_amp = sinx_amp;
    bg->sinx_offset = sinx_offset;
    bg->sinx_period = sinx_period;
    bg->siny_amp = siny_amp;
    bg->siny_offset = siny_offset;
    bg->siny_period = siny_period;
    bg->velocityx = velocityx;
    bg->velocityy = velocityy;

    //Global::debug(1) << "Positionlinked bg: " << bg->name << " set to x: " << bg->startx << " y: " << bg->starty << endl;
}

<|endoftext|>


<commit_before>#pragma once

#include "FarPluginBase.hpp"
#include "array.hpp"

#include "FarDialog.hpp"
#include "FarMessage.hpp"
#include "FarMenu.hpp"
<commit_msg>cleanup<commit_after><|endoftext|>


<commit_before>/*  -*-c++-*-
 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgAnimation/Animation>

using namespace osgAnimation;

Animation::Animation(const osgAnimation::Animation& anim, const osg::CopyOp& copyop): osg::Object(anim, copyop),
    _duration(anim._duration),
    _originalDuration(anim._originalDuration),
    _weight(anim._weight),
    _startTime(anim._startTime),
    _playmode(anim._playmode)
{
    const ChannelList& cl = anim.getChannels();
    for (ChannelList::const_iterator it = cl.begin(); it != cl.end(); ++it)
    {
        addChannel(it->get()->clone());
    }
}

void Animation::addChannel(Channel* pChannel)
{
    _channels.push_back(pChannel);
    if (_duration == _originalDuration)
        computeDuration();
    else
        _originalDuration = computeDurationFromChannels();
}

double Animation::computeDurationFromChannels() const
{
    double tmin = 1e5;
    double tmax = -1e5;
    ChannelList::const_iterator chan;
    for( chan=_channels.begin(); chan!=_channels.end(); chan++ )
    {
        float min = (*chan)->getStartTime();
        if (min < tmin)
            tmin = min;
        float max = (*chan)->getEndTime();
        if (max > tmax)
            tmax = max;
    }
    return tmax-tmin;
}

void Animation::computeDuration()
{
    _duration = computeDurationFromChannels();
    _originalDuration = _duration;
}

osgAnimation::ChannelList& Animation::getChannels()
{
    return _channels;
}

const osgAnimation::ChannelList& Animation::getChannels() const
{
    return _channels;
}

void Animation::setDuration(double duration)
{
    _originalDuration = computeDurationFromChannels();
    _duration = duration;
}

double Animation::getDuration() const
{
    return _duration;
}

float Animation::getWeight () const
{
    return _weight;
}

void Animation::setWeight (float weight)
{
    _weight = weight;
}

bool Animation::update (double time, int priority)
{
    if (!_duration) // if not initialized then do it
        computeDuration();

    double ratio = _originalDuration / _duration;

    double t = (time - _startTime) * ratio;
    switch (_playmode)
    {
    case ONCE:
        if (t > _originalDuration)
            return false;
        break;
    case STAY:
        if (t > _originalDuration)
            t = _originalDuration;
        break;
    case LOOP:
        if (!_originalDuration)
            t = _startTime;
        else if (t > _originalDuration)
            t = fmod(t, _originalDuration);
        //      std::cout << "t " << t << " duration " << _duration << std::endl;
        break;
    case PPONG:
        if (!_originalDuration)
            t = _startTime;
        else
        {
            int tt = (int) (t / _originalDuration);
            t = fmod(t, _originalDuration);
            if (tt%2)
                t = _originalDuration - t;
        }
        break;
    }

    ChannelList::const_iterator chan;
    for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
    {
        (*chan)->update(t, _weight, priority);
    }
    return true;
}

void Animation::resetTargets()
{
    ChannelList::const_iterator chan;
    for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
        (*chan)->reset();
}
<commit_msg>From Konstantin Matveyev, "Last update in the osgAnimation::Animation ONCE mode bug fix"<commit_after>/*  -*-c++-*-
 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgAnimation/Animation>

using namespace osgAnimation;

Animation::Animation(const osgAnimation::Animation& anim, const osg::CopyOp& copyop): osg::Object(anim, copyop),
    _duration(anim._duration),
    _originalDuration(anim._originalDuration),
    _weight(anim._weight),
    _startTime(anim._startTime),
    _playmode(anim._playmode)
{
    const ChannelList& cl = anim.getChannels();
    for (ChannelList::const_iterator it = cl.begin(); it != cl.end(); ++it)
    {
        addChannel(it->get()->clone());
    }
}

void Animation::addChannel(Channel* pChannel)
{
    _channels.push_back(pChannel);
    if (_duration == _originalDuration)
        computeDuration();
    else
        _originalDuration = computeDurationFromChannels();
}

double Animation::computeDurationFromChannels() const
{
    double tmin = 1e5;
    double tmax = -1e5;
    ChannelList::const_iterator chan;
    for( chan=_channels.begin(); chan!=_channels.end(); chan++ )
    {
        float min = (*chan)->getStartTime();
        if (min < tmin)
            tmin = min;
        float max = (*chan)->getEndTime();
        if (max > tmax)
            tmax = max;
    }
    return tmax-tmin;
}

void Animation::computeDuration()
{
    _duration = computeDurationFromChannels();
    _originalDuration = _duration;
}

osgAnimation::ChannelList& Animation::getChannels()
{
    return _channels;
}

const osgAnimation::ChannelList& Animation::getChannels() const
{
    return _channels;
}

void Animation::setDuration(double duration)
{
    _originalDuration = computeDurationFromChannels();
    _duration = duration;
}

double Animation::getDuration() const
{
    return _duration;
}

float Animation::getWeight () const
{
    return _weight;
}

void Animation::setWeight (float weight)
{
    _weight = weight;
}

bool Animation::update (double time, int priority)
{
    if (!_duration) // if not initialized then do it
        computeDuration();

    double ratio = _originalDuration / _duration;

    double t = (time - _startTime) * ratio;
    switch (_playmode)
    {
    case ONCE:
        if (t > _originalDuration)
        {
            for (ChannelList::const_iterator chan = _channels.begin();
                     chan != _channels.end(); ++chan)
                (*chan)->update(_originalDuration, _weight, priority);

            return false;
        }
        break;
    case STAY:
        if (t > _originalDuration)
            t = _originalDuration;
        break;
    case LOOP:
        if (!_originalDuration)
            t = _startTime;
        else if (t > _originalDuration)
            t = fmod(t, _originalDuration);
        //      std::cout << "t " << t << " duration " << _duration << std::endl;
        break;
    case PPONG:
        if (!_originalDuration)
            t = _startTime;
        else
        {
            int tt = (int) (t / _originalDuration);
            t = fmod(t, _originalDuration);
            if (tt%2)
                t = _originalDuration - t;
        }
        break;
    }

    ChannelList::const_iterator chan;
    for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
    {
        (*chan)->update(t, _weight, priority);
    }
    return true;
}

void Animation::resetTargets()
{
    ChannelList::const_iterator chan;
    for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
        (*chan)->reset();
}
<|endoftext|>