<commit_before>/*
 * Copyright 2007-2022 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "http/CookieExtract.hxx"

#include <gtest/gtest.h>

using std::string_view_literals::operator""sv;

TEST(CookieExtract, Basic)
{
	constexpr auto input = "a=b"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "c").data(), nullptr);
	ASSERT_EQ(ExtractCookieRaw(input, "a"), "b"sv);
}

TEST(CookieExtract, Basic2)
{
	constexpr auto input = "c=d;e=f"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "c"), "d"sv);
	ASSERT_EQ(ExtractCookieRaw(input, "e"), "f"sv);
}

TEST(CookieExtract, Quoted)
{
	constexpr auto input = "quoted=\"quoted!\\\\"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "quoted"), "quoted!\\\\");
}

TEST(CookieExtract, Invalid1)
{
	constexpr auto input = "invalid1=foo\t"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "invalid1"), "foo");
}

TEST(CookieExtract, Invalid2)
{
	/* this is actually invalid, but unfortunately RFC ignorance is
	   viral, and forces us to accept square brackets :-( */
	constexpr auto input = "invalid2=foo |[bar] ,"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "invalid2"), "foo |[bar] ,");
}
<commit_msg>test/TestCookieExtract: add another "quoted" test<commit_after>/*
 * Copyright 2007-2022 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "http/CookieExtract.hxx"

#include <gtest/gtest.h>

using std::string_view_literals::operator""sv;

TEST(CookieExtract, Basic)
{
	constexpr auto input = "a=b"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "c").data(), nullptr);
	ASSERT_EQ(ExtractCookieRaw(input, "a"), "b"sv);
}

TEST(CookieExtract, Basic2)
{
	constexpr auto input = "c=d;e=f"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "c"), "d"sv);
	ASSERT_EQ(ExtractCookieRaw(input, "e"), "f"sv);
}

TEST(CookieExtract, Quoted)
{
	constexpr auto input = "quoted=\"quoted!\\\\"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "quoted"), "quoted!\\\\");
}

TEST(CookieExtract, Quoted2)
{
	constexpr auto input = "quoted=\"quoted!\\\\\""sv;
	ASSERT_EQ(ExtractCookieRaw(input, "quoted"), "quoted!\\\\");
}

TEST(CookieExtract, Invalid1)
{
	constexpr auto input = "invalid1=foo\t"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "invalid1"), "foo");
}

TEST(CookieExtract, Invalid2)
{
	/* this is actually invalid, but unfortunately RFC ignorance is
	   viral, and forces us to accept square brackets :-( */
	constexpr auto input = "invalid2=foo |[bar] ,"sv;
	ASSERT_EQ(ExtractCookieRaw(input, "invalid2"), "foo |[bar] ,");
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmlproject.h"
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectrunconfiguration.h"
#include "qmlprojecttarget.h"

#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/ifile.h>
#include <utils/synchronousprocess.h>
#include <utils/pathchooser.h>

#include <QFormLayout>
#include <QComboBox>
#include <QCoreApplication>
#include <QLineEdit>
#include <QSpinBox>

namespace QmlProjectManager {

QmlProjectRunConfiguration::QmlProjectRunConfiguration(Internal::QmlProjectTarget *parent) :
    ProjectExplorer::RunConfiguration(parent, QLatin1String(Constants::QML_RC_ID)),
    m_debugServerAddress("127.0.0.1"),
    m_debugServerPort(Constants::QML_DEFAULT_DEBUG_SERVER_PORT)
{
    ctor();
}

QmlProjectRunConfiguration::QmlProjectRunConfiguration(Internal::QmlProjectTarget *parent, QmlProjectRunConfiguration *source) :
    ProjectExplorer::RunConfiguration(parent, source),
    m_scriptFile(source->m_scriptFile),
    m_qmlViewerCustomPath(source->m_qmlViewerCustomPath),
    m_qmlViewerArgs(source->m_qmlViewerArgs),
    m_debugServerAddress(source->m_debugServerAddress),
    m_debugServerPort(source->m_debugServerPort)
{
    ctor();
}

void QmlProjectRunConfiguration::ctor()
{
    setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name."));

    // prepend creator/bin dir to search path (only useful for special creator-qml package)
    const QString searchPath = QCoreApplication::applicationDirPath()
                               + Utils::SynchronousProcess::pathSeparator()
                               + QString(qgetenv("PATH"));
    m_qmlViewerDefaultPath = Utils::SynchronousProcess::locateBinary(searchPath, QLatin1String("qmlviewer"));
}

QmlProjectRunConfiguration::~QmlProjectRunConfiguration()
{
}

QString QmlProjectRunConfiguration::debugServerAddress() const
{
    return m_debugServerAddress;
}

Internal::QmlProjectTarget *QmlProjectRunConfiguration::qmlTarget() const
{
    return static_cast<Internal::QmlProjectTarget *>(target());
}

QString QmlProjectRunConfiguration::viewerPath() const
{
    if (!m_qmlViewerCustomPath.isEmpty())
        return m_qmlViewerCustomPath;
    return m_qmlViewerDefaultPath;
}

QStringList QmlProjectRunConfiguration::viewerArguments() const
{
    QStringList args;

    // arguments in .user file
    if (!m_qmlViewerArgs.isEmpty())
        args.append(m_qmlViewerArgs);

    // arguments from .qmlproject file
    foreach (const QString &libraryPath, qmlTarget()->qmlProject()->libraryPaths()) {
        args.append(QLatin1String("-L"));
        args.append(libraryPath);
    }

    const QString s = mainScript();
    if (! s.isEmpty())
        args.append(s);
    return args;
}

QString QmlProjectRunConfiguration::workingDirectory() const
{
    QFileInfo projectFile(qmlTarget()->qmlProject()->file()->fileName());
    return projectFile.absolutePath();
}

uint QmlProjectRunConfiguration::debugServerPort() const
{
    return m_debugServerPort;
}

QWidget *QmlProjectRunConfiguration::configurationWidget()
{
    QWidget *config = new QWidget;
    QFormLayout *form = new QFormLayout(config);

    QComboBox *combo = new QComboBox;

    QDir projectDir = qmlTarget()->qmlProject()->projectDir();
    QStringList files;

    files.append(tr("<Current File>"));

    int currentIndex = -1;

    foreach (const QString &fn, qmlTarget()->qmlProject()->files()) {
        QFileInfo fileInfo(fn);
        if (fileInfo.suffix() != QLatin1String("qml"))
            continue;

        QString fileName = projectDir.relativeFilePath(fn);
        if (fileName == m_scriptFile)
            currentIndex = files.size();

        files.append(fileName);
    }

    combo->addItems(files);
    if (currentIndex != -1)
        combo->setCurrentIndex(currentIndex);

    connect(combo, SIGNAL(activated(QString)), this, SLOT(setMainScript(QString)));

    Utils::PathChooser *qmlViewer = new Utils::PathChooser;
    qmlViewer->setExpectedKind(Utils::PathChooser::Command);
    qmlViewer->setPath(viewerPath());
    connect(qmlViewer, SIGNAL(changed(QString)), this, SLOT(onQmlViewerChanged()));

    QLineEdit *qmlViewerArgs = new QLineEdit;
    qmlViewerArgs->setText(m_qmlViewerArgs);
    connect(qmlViewerArgs, SIGNAL(textChanged(QString)), this, SLOT(onQmlViewerArgsChanged()));

    QLineEdit *debugServer = new QLineEdit;
    debugServer->setText(m_debugServerAddress);
    connect(debugServer, SIGNAL(textChanged(QString)), this, SLOT(onDebugServerAddressChanged()));

    QSpinBox *debugPort = new QSpinBox;
    debugPort->setMinimum(1024); // valid registered/dynamic/free ports according to http://www.iana.org/assignments/port-numbers
    debugPort->setMaximum(65535);
    debugPort->setValue(m_debugServerPort);
    connect(debugPort, SIGNAL(valueChanged(int)), this, SLOT(onDebugServerPortChanged()));

    form->addRow(tr("QML Viewer"), qmlViewer);
    form->addRow(tr("QML Viewer arguments:"), qmlViewerArgs);
    form->addRow(tr("Main QML File:"), combo);
    form->addRow(tr("Debugging Address:"), debugServer);
    form->addRow(tr("Debugging Port:"), debugPort);

    return config;
}

QString QmlProjectRunConfiguration::mainScript() const
{
    if (m_scriptFile.isEmpty() || m_scriptFile == tr("<Current File>")) {
        Core::EditorManager *editorManager = Core::ICore::instance()->editorManager();
        if (Core::IEditor *editor = editorManager->currentEditor()) {
            return editor->file()->fileName();
        }
    }

    return qmlTarget()->qmlProject()->projectDir().absoluteFilePath(m_scriptFile);
}

void QmlProjectRunConfiguration::setMainScript(const QString &scriptFile)
{
    m_scriptFile = scriptFile;
}

void QmlProjectRunConfiguration::onQmlViewerChanged()
{
    if (Utils::PathChooser *chooser = qobject_cast<Utils::PathChooser *>(sender())) {
        m_qmlViewerCustomPath = chooser->path();
    }
}

void QmlProjectRunConfiguration::onQmlViewerArgsChanged()
{
    if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender()))
        m_qmlViewerArgs = lineEdit->text();
}

void QmlProjectRunConfiguration::onDebugServerPortChanged()
{
    if (QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender())) {
        m_debugServerPort = spinBox->value();
    }
}

QVariantMap QmlProjectRunConfiguration::toMap() const
{
    QVariantMap map(ProjectExplorer::RunConfiguration::toMap());

    map.insert(QLatin1String(Constants::QML_VIEWER_KEY), m_qmlViewerCustomPath);
    map.insert(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY), m_qmlViewerArgs);
    map.insert(QLatin1String(Constants::QML_MAINSCRIPT_KEY),  m_scriptFile);
    map.insert(QLatin1String(Constants::QML_DEBUG_SERVER_PORT_KEY), m_debugServerPort);
    return map;
}

bool QmlProjectRunConfiguration::fromMap(const QVariantMap &map)
{
    m_qmlViewerCustomPath = map.value(QLatin1String(Constants::QML_VIEWER_KEY)).toString();
    m_qmlViewerArgs = map.value(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY)).toString();
    m_scriptFile = map.value(QLatin1String(Constants::QML_MAINSCRIPT_KEY), tr("<Current File>")).toString();
    m_debugServerPort = map.value(QLatin1String(Constants::QML_DEBUG_SERVER_PORT_KEY), Constants::QML_DEFAULT_DEBUG_SERVER_PORT).toUInt();

    return RunConfiguration::fromMap(map);
}

} // namespace QmlProjectManager
<commit_msg>Added a missing slot implementation for server address change<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmlproject.h"
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectrunconfiguration.h"
#include "qmlprojecttarget.h"

#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/ifile.h>
#include <utils/synchronousprocess.h>
#include <utils/pathchooser.h>

#include <QFormLayout>
#include <QComboBox>
#include <QCoreApplication>
#include <QLineEdit>
#include <QSpinBox>

namespace QmlProjectManager {

QmlProjectRunConfiguration::QmlProjectRunConfiguration(Internal::QmlProjectTarget *parent) :
    ProjectExplorer::RunConfiguration(parent, QLatin1String(Constants::QML_RC_ID)),
    m_debugServerAddress("127.0.0.1"),
    m_debugServerPort(Constants::QML_DEFAULT_DEBUG_SERVER_PORT)
{
    ctor();
}

QmlProjectRunConfiguration::QmlProjectRunConfiguration(Internal::QmlProjectTarget *parent, QmlProjectRunConfiguration *source) :
    ProjectExplorer::RunConfiguration(parent, source),
    m_scriptFile(source->m_scriptFile),
    m_qmlViewerCustomPath(source->m_qmlViewerCustomPath),
    m_qmlViewerArgs(source->m_qmlViewerArgs),
    m_debugServerAddress(source->m_debugServerAddress),
    m_debugServerPort(source->m_debugServerPort)
{
    ctor();
}

void QmlProjectRunConfiguration::ctor()
{
    setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name."));

    // prepend creator/bin dir to search path (only useful for special creator-qml package)
    const QString searchPath = QCoreApplication::applicationDirPath()
                               + Utils::SynchronousProcess::pathSeparator()
                               + QString(qgetenv("PATH"));
    m_qmlViewerDefaultPath = Utils::SynchronousProcess::locateBinary(searchPath, QLatin1String("qmlviewer"));
}

QmlProjectRunConfiguration::~QmlProjectRunConfiguration()
{
}

QString QmlProjectRunConfiguration::debugServerAddress() const
{
    return m_debugServerAddress;
}

Internal::QmlProjectTarget *QmlProjectRunConfiguration::qmlTarget() const
{
    return static_cast<Internal::QmlProjectTarget *>(target());
}

QString QmlProjectRunConfiguration::viewerPath() const
{
    if (!m_qmlViewerCustomPath.isEmpty())
        return m_qmlViewerCustomPath;
    return m_qmlViewerDefaultPath;
}

QStringList QmlProjectRunConfiguration::viewerArguments() const
{
    QStringList args;

    // arguments in .user file
    if (!m_qmlViewerArgs.isEmpty())
        args.append(m_qmlViewerArgs);

    // arguments from .qmlproject file
    foreach (const QString &libraryPath, qmlTarget()->qmlProject()->libraryPaths()) {
        args.append(QLatin1String("-L"));
        args.append(libraryPath);
    }

    const QString s = mainScript();
    if (! s.isEmpty())
        args.append(s);
    return args;
}

QString QmlProjectRunConfiguration::workingDirectory() const
{
    QFileInfo projectFile(qmlTarget()->qmlProject()->file()->fileName());
    return projectFile.absolutePath();
}

uint QmlProjectRunConfiguration::debugServerPort() const
{
    return m_debugServerPort;
}

QWidget *QmlProjectRunConfiguration::configurationWidget()
{
    QWidget *config = new QWidget;
    QFormLayout *form = new QFormLayout(config);

    QComboBox *combo = new QComboBox;

    QDir projectDir = qmlTarget()->qmlProject()->projectDir();
    QStringList files;

    files.append(tr("<Current File>"));

    int currentIndex = -1;

    foreach (const QString &fn, qmlTarget()->qmlProject()->files()) {
        QFileInfo fileInfo(fn);
        if (fileInfo.suffix() != QLatin1String("qml"))
            continue;

        QString fileName = projectDir.relativeFilePath(fn);
        if (fileName == m_scriptFile)
            currentIndex = files.size();

        files.append(fileName);
    }

    combo->addItems(files);
    if (currentIndex != -1)
        combo->setCurrentIndex(currentIndex);

    connect(combo, SIGNAL(activated(QString)), this, SLOT(setMainScript(QString)));

    Utils::PathChooser *qmlViewer = new Utils::PathChooser;
    qmlViewer->setExpectedKind(Utils::PathChooser::Command);
    qmlViewer->setPath(viewerPath());
    connect(qmlViewer, SIGNAL(changed(QString)), this, SLOT(onQmlViewerChanged()));

    QLineEdit *qmlViewerArgs = new QLineEdit;
    qmlViewerArgs->setText(m_qmlViewerArgs);
    connect(qmlViewerArgs, SIGNAL(textChanged(QString)), this, SLOT(onQmlViewerArgsChanged()));

    QLineEdit *debugServer = new QLineEdit;
    debugServer->setText(m_debugServerAddress);
    connect(debugServer, SIGNAL(textChanged(QString)), this, SLOT(onDebugServerAddressChanged()));

    QSpinBox *debugPort = new QSpinBox;
    debugPort->setMinimum(1024); // valid registered/dynamic/free ports according to http://www.iana.org/assignments/port-numbers
    debugPort->setMaximum(65535);
    debugPort->setValue(m_debugServerPort);
    connect(debugPort, SIGNAL(valueChanged(int)), this, SLOT(onDebugServerPortChanged()));

    form->addRow(tr("QML Viewer"), qmlViewer);
    form->addRow(tr("QML Viewer arguments:"), qmlViewerArgs);
    form->addRow(tr("Main QML File:"), combo);
    form->addRow(tr("Debugging Address:"), debugServer);
    form->addRow(tr("Debugging Port:"), debugPort);

    return config;
}

QString QmlProjectRunConfiguration::mainScript() const
{
    if (m_scriptFile.isEmpty() || m_scriptFile == tr("<Current File>")) {
        Core::EditorManager *editorManager = Core::ICore::instance()->editorManager();
        if (Core::IEditor *editor = editorManager->currentEditor()) {
            return editor->file()->fileName();
        }
    }

    return qmlTarget()->qmlProject()->projectDir().absoluteFilePath(m_scriptFile);
}

void QmlProjectRunConfiguration::onDebugServerAddressChanged()
{
    if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender()))
        m_debugServerAddress = lineEdit->text();
}

void QmlProjectRunConfiguration::setMainScript(const QString &scriptFile)
{
    m_scriptFile = scriptFile;
}

void QmlProjectRunConfiguration::onQmlViewerChanged()
{
    if (Utils::PathChooser *chooser = qobject_cast<Utils::PathChooser *>(sender())) {
        m_qmlViewerCustomPath = chooser->path();
    }
}

void QmlProjectRunConfiguration::onQmlViewerArgsChanged()
{
    if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender()))
        m_qmlViewerArgs = lineEdit->text();
}

void QmlProjectRunConfiguration::onDebugServerPortChanged()
{
    if (QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender())) {
        m_debugServerPort = spinBox->value();
    }
}

QVariantMap QmlProjectRunConfiguration::toMap() const
{
    QVariantMap map(ProjectExplorer::RunConfiguration::toMap());

    map.insert(QLatin1String(Constants::QML_VIEWER_KEY), m_qmlViewerCustomPath);
    map.insert(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY), m_qmlViewerArgs);
    map.insert(QLatin1String(Constants::QML_MAINSCRIPT_KEY),  m_scriptFile);
    map.insert(QLatin1String(Constants::QML_DEBUG_SERVER_PORT_KEY), m_debugServerPort);
    return map;
}

bool QmlProjectRunConfiguration::fromMap(const QVariantMap &map)
{
    m_qmlViewerCustomPath = map.value(QLatin1String(Constants::QML_VIEWER_KEY)).toString();
    m_qmlViewerArgs = map.value(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY)).toString();
    m_scriptFile = map.value(QLatin1String(Constants::QML_MAINSCRIPT_KEY), tr("<Current File>")).toString();
    m_debugServerPort = map.value(QLatin1String(Constants::QML_DEBUG_SERVER_PORT_KEY), Constants::QML_DEFAULT_DEBUG_SERVER_PORT).toUInt();

    return RunConfiguration::fromMap(map);
}

} // namespace QmlProjectManager
<|endoftext|>


<commit_before>/*
** Copyright (C) 2014 Aldebaran
*/
#include <qi/application.hpp>
#include <qi/future.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/foreach.hpp>
#include <qi/os.hpp>
#include <qi/strand.hpp>
#include <qi/periodictask.hpp>
#include <qi/actor.hpp>
#include <qi/log.hpp>
#include <qi/anyobject.hpp>
#include <qi/type/dynamicobjectbuilder.hpp>
#include <gtest/gtest.h>

qiLogCategory("test");

void setValueWait(boost::mutex& mutex, int waittime, int& i, int v)
{
  boost::unique_lock<boost::mutex> lock(mutex, boost::try_to_lock);
  // we should never be called in parallel
  ASSERT_TRUE(lock.owns_lock());
  if (waittime)
    qi::os::msleep(waittime);
  i = v;
}

TEST(TestStrand, StrandSimple)
{
  boost::mutex mutex;

  qi::Strand strand(*qi::getEventLoop());
  int i = 0;
  qi::Future<void> f1 = strand.async(boost::bind<void>(&setValueWait,
        boost::ref(mutex), 100, boost::ref(i), 1));
  qi::os::msleep(5);
  EXPECT_FALSE(f1.isFinished());
  qi::Future<void> f2 = strand.async(boost::bind<void>(&setValueWait,
        boost::ref(mutex), 0, boost::ref(i), 2));
  qi::os::msleep(200);
  EXPECT_EQ(i, 2);
}

static void fail()
{
  ASSERT_TRUE(false);
}

TEST(TestStrand, StrandCancel)
{
  qi::Strand strand(*qi::getEventLoop());
  // cancel before scheduling
  qi::Future<void> f1 = strand.asyncDelay(fail, qi::Seconds(1000));
  f1.cancel();
  ASSERT_EQ(qi::FutureState_Canceled, f1.wait());
}

TEST(TestStrand, StrandCancelScheduled)
{
  qi::Strand strand(*qi::getEventLoop());
  // cancel before scheduling
  qi::Future<void> f1 = strand.async(boost::bind(qi::os::msleep, 100));
  qi::Future<void> f2 = strand.async(fail);
  qi::os::msleep(30);
  f2.cancel();
  ASSERT_EQ(qi::FutureState_FinishedWithValue, f1.wait()) << f1.error();
  ASSERT_EQ(qi::FutureState_Canceled, f2.wait());
}

static void increment(boost::mutex& mutex, int waittime, boost::atomic<unsigned int>& i)
{
  boost::unique_lock<boost::mutex> lock(mutex, boost::try_to_lock);
  // we should never be called in parallel
  ASSERT_TRUE(lock.owns_lock());
  if (waittime)
    qi::os::msleep(waittime);
  ++i;
}

static const unsigned int STRAND_NB_TRIES = 100;

TEST(TestStrand, AggressiveCancel)
{
  boost::mutex mutex;
  std::vector<qi::Future<void> > futures;

  qi::Strand strand(*qi::getEventLoop());
  boost::atomic<unsigned int> i(0);
  for (unsigned int j = 0; j < STRAND_NB_TRIES; ++j)
  {
    qi::Future<void> f1 = strand.async(boost::bind<void>(&increment,
          boost::ref(mutex), 1, boost::ref(i)));
    futures.push_back(f1);
    f1 = strand.async(boost::bind<void>(&increment,
          boost::ref(mutex), 50, boost::ref(i)));
    futures.push_back(f1);
  }
  BOOST_FOREACH(qi::Future<void>& future, futures)
    future.cancel();

  unsigned int successCount = 0;
  BOOST_FOREACH(qi::Future<void>& future, futures)
  {
    if (future.wait() != qi::FutureState_Canceled)
      successCount++;
  }
  if (i == futures.size() || i == 0)
    qiLogWarning() << "i = " << i <<
      ", this test is meaningless, you should do something about that";
  ASSERT_EQ(successCount, i);
}

TEST(TestStrand, StrandDestruction)
{
  boost::mutex mutex;
  boost::atomic<unsigned int> i(0);

  std::vector<qi::Future<void>> futures;
  {
    qi::Strand strand(*qi::getEventLoop());
    futures.reserve(STRAND_NB_TRIES);
    for (unsigned int j = 0; j < STRAND_NB_TRIES; ++j)
    {
      futures.push_back(strand.async(boost::bind<void>(&increment,
              boost::ref(mutex), 1, boost::ref(i))));
    }
  }
  for (auto& future : futures)
    ASSERT_TRUE(future.isFinished());
}

TEST(TestStrand, StrandDestructionWithMethodAndConcurrency)
{
  // ASSERT_NOSEGFAULT_NOCRASH_NOBADTHINGS();
  boost::mutex mutex;
  boost::atomic<unsigned int> i(0);

  std::vector<qi::Future<void>> futures;
  qi::Strand strand(*qi::getEventLoop());
  futures.reserve(STRAND_NB_TRIES);
  for (unsigned int j = 0; j < STRAND_NB_TRIES/4; ++j)
    futures.push_back(qi::getEventLoop()->async([&]{
            strand.async(boost::bind<void>(&increment,
                boost::ref(mutex), 1, boost::ref(i)));
          }));
  for (unsigned int j = 0; j < STRAND_NB_TRIES/4; ++j)
    strand.async(boost::bind<void>(&increment,
            boost::ref(mutex), 1, boost::ref(i)));
  strand.join();
  for (unsigned int j = 0; j < STRAND_NB_TRIES/4; ++j)
    futures.push_back(qi::getEventLoop()->async([&]{
            strand.async(boost::bind<void>(&increment,
                boost::ref(mutex), 1, boost::ref(i)));
          }));
  for (unsigned int j = 0; j < STRAND_NB_TRIES/4; ++j)
    strand.async(boost::bind<void>(&increment,
            boost::ref(mutex), 1, boost::ref(i)));
  for (auto& future : futures)
    ASSERT_TRUE(future.wait());
}

TEST(TestStrand, StrandDestructionWithCancel)
{
  boost::mutex mutex;
  std::vector<qi::Future<void> > futures;
  boost::atomic<unsigned int> i(0);

  {
    qi::Strand strand(*qi::getEventLoop());
    for (unsigned int j = 0; j < STRAND_NB_TRIES; ++j)
    {
      qi::Future<void> f1 = strand.async(boost::bind<void>(&increment,
            boost::ref(mutex), 1, boost::ref(i)));
      futures.push_back(f1);
      f1 = strand.async(boost::bind<void>(&increment,
            boost::ref(mutex), 50, boost::ref(i)));
      futures.push_back(f1);
    }
    BOOST_FOREACH(qi::Future<void>& future, futures)
      future.cancel();
  }

  unsigned int successCount = 0;
  BOOST_FOREACH(qi::Future<void>& future, futures)
  {
    if (future.wait() != qi::FutureState_Canceled)
      successCount++;
  }
  if (i == futures.size() || i == 0)
    qiLogWarning() << "i = " << i <<
      ", this test is meaningless, you should do something about that";
  ASSERT_EQ(successCount, i);
}

static void deleteStrand(qi::Strand* strand)
{
  delete strand;
}

TEST(TestStrand, StrandDestructionBeforeEnd)
{
  qi::Strand* strand = new qi::Strand(*qi::getEventLoop());
  qi::Future<void> f = strand->async(boost::bind(deleteStrand, strand));
  f.value();
}

boost::atomic<int> callcount;

struct MyActor : qi::Actor
{
  boost::atomic<bool> calling;
  MyActor() : calling(0) {}
  ~MyActor() { strand()->join(); }
  int f(int end, qi::Promise<void> finished)
  {
    int startval = prop.get();
    EXPECT_FALSE(calling);
    calling = true;
    qi::os::msleep(5);
    EXPECT_TRUE(calling);
    calling = false;
    EXPECT_EQ(startval, prop.get());
    if (++callcount == end + 1)
      finished.setValue(0);
    return 42;
  }
  qi::Signal<int> sig;
  qi::Property<int> prop;
};
QI_REGISTER_OBJECT(MyActor, f, sig, prop);

TEST(TestStrand, AllFutureSignalPropertyPeriodicTaskAsyncTypeErasedDynamic)
{
  static const int TOTAL = 50;
  srand(1828);

  callcount = 0;
  {
    boost::shared_ptr<MyActor> obj(new MyActor);

    qi::DynamicObjectBuilder builder;
    builder.setThreadingModel(qi::ObjectThreadingModel_SingleThread);
    builder.advertiseMethod("f",
        boost::function<void(int, qi::Promise<void>)>(boost::bind(&MyActor::f, obj, _1, _2)));
    builder.advertiseSignal("sig", &obj->sig);
    builder.advertiseProperty("prop", &obj->prop);

    qi::AnyObject aobj(builder.object());

    qi::Promise<void> finished;

    for (int i = 0; i < 25; ++i)
      aobj.async<void>("f", TOTAL, finished);
    for (int i = 0; i < 50; ++i)
      aobj.setProperty("prop", rand());
    QI_EMIT obj->sig(TOTAL);
    // we need one more call (the second test expects a periodic task to run at
    // least once)
    for (int i = 0; i < 26; ++i)
      aobj.async<void>("f", TOTAL, finished);
    finished.future().wait();
  }
  ASSERT_EQ(TOTAL + 1, callcount);
}

void chaincall(qi::AnyObject aobj, qi::Promise<void> finished, int TOTAL)
{
  for (int i = 0; i < 50; ++i)
    EXPECT_EQ(42, aobj.call<int>("f", TOTAL, finished));
}

TEST(TestStrand, AllFutureSignalPropertyPeriodicTaskAsyncCallTypeErased)
{
  static const int TOTAL = 300;
  srand(1828);

  callcount = 0;
  {
    boost::shared_ptr<MyActor> obj(new MyActor);
    qi::AnyObject aobj(obj);

    qi::Promise<void> finished;

    qi::PeriodicTask per;
    per.setUsPeriod(30);
    per.setCallback(&MyActor::f, obj.get(), TOTAL, finished);

    qi::Promise<void> prom;
    qi::Signal<int> signal;

    static_assert(std::is_same<decltype(prom.future().andThen(qi::bind(&MyActor::f, obj.get(), TOTAL, finished))), qi::Future<int>>::value, "andThen future type incorrect");
    static_assert(std::is_same<decltype(prom.future().then(qi::bind(&MyActor::f, obj.get(), TOTAL, finished))), qi::Future<int>>::value, "then future type incorrect");

    for (int i = 0; i < 25; ++i)
      prom.future().connect(&MyActor::f, obj.get(), TOTAL, finished);
    for (int i = 0; i < 10; ++i)
      prom.future().thenR<int>(&MyActor::f, obj.get(), TOTAL, finished);
    for (int i = 0; i < 10; ++i)
      prom.future().andThen(qi::bind(&MyActor::f, obj.get(), TOTAL, finished));
    for (int i = 0; i < 5; ++i)
      prom.future().then(qi::bind(&MyActor::f, obj.get(), TOTAL, finished));
    for (int i = 0; i < 50; ++i)
      signal.connect(&MyActor::f, obj.get(), _1, finished);
    for (int i = 0; i < 50; ++i)
      aobj.connect("sig", boost::function<void(int)>(obj->strand()->schedulerFor(boost::bind(&MyActor::f, obj, _1, finished))));

    per.start();
    for (int i = 0; i < 25; ++i)
      aobj.async<void>("f", TOTAL, finished);
    for (int i = 0; i < 25; ++i)
      qi::async(qi::bind(&MyActor::f, obj, TOTAL, finished));
    for (int i = 0; i < 50; ++i)
      aobj.setProperty("prop", rand());
    qi::Future<void> f = qi::async(boost::bind(chaincall, aobj, finished, TOTAL));
    prom.setValue(0);
    QI_EMIT signal(TOTAL);
    QI_EMIT obj->sig(TOTAL);
    for (int i = 0; i < 25; ++i)
      aobj.async<void>("f", TOTAL, finished);
    for (int i = 0; i < 25; ++i)
      qi::async(qi::bind(&MyActor::f, obj, TOTAL, finished));
    f.wait();
    finished.future().wait();
  }
  ASSERT_LT(TOTAL, callcount);
}

TEST(TestStrand, FutureThenActorCancel)
{
  callcount = 0;
  {
    boost::shared_ptr<MyActor> obj(new MyActor);
    qi::AnyObject aobj(obj);

    qi::Promise<void> finished;

    qi::Promise<int> prom(qi::PromiseNoop<int>);
    qi::Future<int> masterFut = prom.future().thenR<int>(&MyActor::f, obj, _1, finished);
    masterFut.cancel();
    ASSERT_TRUE(prom.isCancelRequested());
    prom.setValue(0);
    ASSERT_EQ(42, masterFut.value());
    ASSERT_NO_THROW(finished.future().value());
  }
}

int main(int argc, char* argv[])
{
  qi::Application app(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  // better for these tests, since a task is 5ms long
  qi::os::setenv("QI_STRAND_QUANTUM_US", "50000");
  return RUN_ALL_TESTS();
}
<commit_msg>Actor: add test for calls with success and error<commit_after>/*
** Copyright (C) 2014 Aldebaran
*/
#include <qi/application.hpp>
#include <qi/future.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/foreach.hpp>
#include <qi/os.hpp>
#include <qi/strand.hpp>
#include <qi/periodictask.hpp>
#include <qi/actor.hpp>
#include <qi/log.hpp>
#include <qi/anyobject.hpp>
#include <qi/type/dynamicobjectbuilder.hpp>
#include <gtest/gtest.h>

qiLogCategory("test");

void setValueWait(boost::mutex& mutex, int waittime, int& i, int v)
{
  boost::unique_lock<boost::mutex> lock(mutex, boost::try_to_lock);
  // we should never be called in parallel
  ASSERT_TRUE(lock.owns_lock());
  if (waittime)
    qi::os::msleep(waittime);
  i = v;
}

TEST(TestStrand, StrandSimple)
{
  boost::mutex mutex;

  qi::Strand strand(*qi::getEventLoop());
  int i = 0;
  qi::Future<void> f1 = strand.async(boost::bind<void>(&setValueWait,
        boost::ref(mutex), 100, boost::ref(i), 1));
  qi::os::msleep(5);
  EXPECT_FALSE(f1.isFinished());
  qi::Future<void> f2 = strand.async(boost::bind<void>(&setValueWait,
        boost::ref(mutex), 0, boost::ref(i), 2));
  qi::os::msleep(200);
  EXPECT_EQ(i, 2);
}

static void fail()
{
  ASSERT_TRUE(false);
}

TEST(TestStrand, StrandCancel)
{
  qi::Strand strand(*qi::getEventLoop());
  // cancel before scheduling
  qi::Future<void> f1 = strand.asyncDelay(fail, qi::Seconds(1000));
  f1.cancel();
  ASSERT_EQ(qi::FutureState_Canceled, f1.wait());
}

TEST(TestStrand, StrandCancelScheduled)
{
  qi::Strand strand(*qi::getEventLoop());
  // cancel before scheduling
  qi::Future<void> f1 = strand.async(boost::bind(qi::os::msleep, 100));
  qi::Future<void> f2 = strand.async(fail);
  qi::os::msleep(30);
  f2.cancel();
  ASSERT_EQ(qi::FutureState_FinishedWithValue, f1.wait()) << f1.error();
  ASSERT_EQ(qi::FutureState_Canceled, f2.wait());
}

static void increment(boost::mutex& mutex, int waittime, boost::atomic<unsigned int>& i)
{
  boost::unique_lock<boost::mutex> lock(mutex, boost::try_to_lock);
  // we should never be called in parallel
  ASSERT_TRUE(lock.owns_lock());
  if (waittime)
    qi::os::msleep(waittime);
  ++i;
}

static const unsigned int STRAND_NB_TRIES = 100;

TEST(TestStrand, AggressiveCancel)
{
  boost::mutex mutex;
  std::vector<qi::Future<void> > futures;

  qi::Strand strand(*qi::getEventLoop());
  boost::atomic<unsigned int> i(0);
  for (unsigned int j = 0; j < STRAND_NB_TRIES; ++j)
  {
    qi::Future<void> f1 = strand.async(boost::bind<void>(&increment,
          boost::ref(mutex), 1, boost::ref(i)));
    futures.push_back(f1);
    f1 = strand.async(boost::bind<void>(&increment,
          boost::ref(mutex), 50, boost::ref(i)));
    futures.push_back(f1);
  }
  BOOST_FOREACH(qi::Future<void>& future, futures)
    future.cancel();

  unsigned int successCount = 0;
  BOOST_FOREACH(qi::Future<void>& future, futures)
  {
    if (future.wait() != qi::FutureState_Canceled)
      successCount++;
  }
  if (i == futures.size() || i == 0)
    qiLogWarning() << "i = " << i <<
      ", this test is meaningless, you should do something about that";
  ASSERT_EQ(successCount, i);
}

TEST(TestStrand, StrandDestruction)
{
  boost::mutex mutex;
  boost::atomic<unsigned int> i(0);

  std::vector<qi::Future<void>> futures;
  {
    qi::Strand strand(*qi::getEventLoop());
    futures.reserve(STRAND_NB_TRIES);
    for (unsigned int j = 0; j < STRAND_NB_TRIES; ++j)
    {
      futures.push_back(strand.async(boost::bind<void>(&increment,
              boost::ref(mutex), 1, boost::ref(i))));
    }
  }
  for (auto& future : futures)
    ASSERT_TRUE(future.isFinished());
}

TEST(TestStrand, StrandDestructionWithMethodAndConcurrency)
{
  // ASSERT_NOSEGFAULT_NOCRASH_NOBADTHINGS();
  boost::mutex mutex;
  boost::atomic<unsigned int> i(0);

  std::vector<qi::Future<void>> futures;
  qi::Strand strand(*qi::getEventLoop());
  futures.reserve(STRAND_NB_TRIES);
  for (unsigned int j = 0; j < STRAND_NB_TRIES/4; ++j)
    futures.push_back(qi::getEventLoop()->async([&]{
            strand.async(boost::bind<void>(&increment,
                boost::ref(mutex), 1, boost::ref(i)));
          }));
  for (unsigned int j = 0; j < STRAND_NB_TRIES/4; ++j)
    strand.async(boost::bind<void>(&increment,
            boost::ref(mutex), 1, boost::ref(i)));
  strand.join();
  for (unsigned int j = 0; j < STRAND_NB_TRIES/4; ++j)
    futures.push_back(qi::getEventLoop()->async([&]{
            strand.async(boost::bind<void>(&increment,
                boost::ref(mutex), 1, boost::ref(i)));
          }));
  for (unsigned int j = 0; j < STRAND_NB_TRIES/4; ++j)
    strand.async(boost::bind<void>(&increment,
            boost::ref(mutex), 1, boost::ref(i)));
  for (auto& future : futures)
    ASSERT_TRUE(future.wait());
}

TEST(TestStrand, StrandDestructionWithCancel)
{
  boost::mutex mutex;
  std::vector<qi::Future<void> > futures;
  boost::atomic<unsigned int> i(0);

  {
    qi::Strand strand(*qi::getEventLoop());
    for (unsigned int j = 0; j < STRAND_NB_TRIES; ++j)
    {
      qi::Future<void> f1 = strand.async(boost::bind<void>(&increment,
            boost::ref(mutex), 1, boost::ref(i)));
      futures.push_back(f1);
      f1 = strand.async(boost::bind<void>(&increment,
            boost::ref(mutex), 50, boost::ref(i)));
      futures.push_back(f1);
    }
    BOOST_FOREACH(qi::Future<void>& future, futures)
      future.cancel();
  }

  unsigned int successCount = 0;
  BOOST_FOREACH(qi::Future<void>& future, futures)
  {
    if (future.wait() != qi::FutureState_Canceled)
      successCount++;
  }
  if (i == futures.size() || i == 0)
    qiLogWarning() << "i = " << i <<
      ", this test is meaningless, you should do something about that";
  ASSERT_EQ(successCount, i);
}

static void deleteStrand(qi::Strand* strand)
{
  delete strand;
}

TEST(TestStrand, StrandDestructionBeforeEnd)
{
  qi::Strand* strand = new qi::Strand(*qi::getEventLoop());
  qi::Future<void> f = strand->async(boost::bind(deleteStrand, strand));
  f.value();
}

boost::atomic<int> callcount;

struct MyActor : qi::Actor
{
  boost::atomic<bool> calling;
  MyActor() : calling(0) {}
  ~MyActor() { strand()->join(); }
  int f(int end, qi::Promise<void> finished)
  {
    int startval = prop.get();
    EXPECT_FALSE(calling);
    calling = true;
    qi::os::msleep(5);
    EXPECT_TRUE(calling);
    calling = false;
    EXPECT_EQ(startval, prop.get());
    if (++callcount == end + 1)
      finished.setValue(0);
    return 42;
  }
  qi::Future<int> val()
  {
    return qi::Future<int>(42);
  }
  qi::Future<int> thrw()
  {
    throw std::runtime_error("throw");
  }
  qi::Future<int> fail()
  {
    return qi::makeFutureError<int>("fail");
  }
  qi::Signal<int> sig;
  qi::Property<int> prop;
};
QI_REGISTER_OBJECT(MyActor, f, val, thrw, fail, sig, prop);

TEST(TestStrand, TypeErasedCall)
{
  boost::shared_ptr<MyActor> obj(new MyActor);
  qi::AnyObject aobj(obj);

  EXPECT_EQ(42, aobj.async<int>("val").value());
  EXPECT_TRUE(aobj.async<int>("thrw").hasError());
  EXPECT_TRUE(aobj.async<int>("fail").hasError());

  EXPECT_EQ(42, aobj.call<int>("val"));
  EXPECT_ANY_THROW(aobj.call<int>("thrw"));
  EXPECT_ANY_THROW(aobj.call<int>("fail"));
}

TEST(TestStrand, AllFutureSignalPropertyPeriodicTaskAsyncTypeErasedDynamic)
{
  static const int TOTAL = 50;
  srand(1828);

  callcount = 0;
  {
    boost::shared_ptr<MyActor> obj(new MyActor);

    qi::DynamicObjectBuilder builder;
    builder.setThreadingModel(qi::ObjectThreadingModel_SingleThread);
    builder.advertiseMethod("f",
        boost::function<void(int, qi::Promise<void>)>(boost::bind(&MyActor::f, obj, _1, _2)));
    builder.advertiseSignal("sig", &obj->sig);
    builder.advertiseProperty("prop", &obj->prop);

    qi::AnyObject aobj(builder.object());

    qi::Promise<void> finished;

    for (int i = 0; i < 25; ++i)
      aobj.async<void>("f", TOTAL, finished);
    for (int i = 0; i < 50; ++i)
      aobj.setProperty("prop", rand());
    QI_EMIT obj->sig(TOTAL);
    // we need one more call (the second test expects a periodic task to run at
    // least once)
    for (int i = 0; i < 26; ++i)
      aobj.async<void>("f", TOTAL, finished);
    finished.future().wait();
  }
  ASSERT_EQ(TOTAL + 1, callcount);
}

void chaincall(qi::AnyObject aobj, qi::Promise<void> finished, int TOTAL)
{
  for (int i = 0; i < 50; ++i)
    EXPECT_EQ(42, aobj.call<int>("f", TOTAL, finished));
}

TEST(TestStrand, AllFutureSignalPropertyPeriodicTaskAsyncCallTypeErased)
{
  static const int TOTAL = 300;
  srand(1828);

  callcount = 0;
  {
    boost::shared_ptr<MyActor> obj(new MyActor);
    qi::AnyObject aobj(obj);

    qi::Promise<void> finished;

    qi::PeriodicTask per;
    per.setUsPeriod(30);
    per.setCallback(&MyActor::f, obj.get(), TOTAL, finished);

    qi::Promise<void> prom;
    qi::Signal<int> signal;

    static_assert(std::is_same<decltype(prom.future().andThen(qi::bind(&MyActor::f, obj.get(), TOTAL, finished))), qi::Future<int>>::value, "andThen future type incorrect");
    static_assert(std::is_same<decltype(prom.future().then(qi::bind(&MyActor::f, obj.get(), TOTAL, finished))), qi::Future<int>>::value, "then future type incorrect");

    for (int i = 0; i < 25; ++i)
      prom.future().connect(&MyActor::f, obj.get(), TOTAL, finished);
    for (int i = 0; i < 10; ++i)
      prom.future().thenR<int>(&MyActor::f, obj.get(), TOTAL, finished);
    for (int i = 0; i < 10; ++i)
      prom.future().andThen(qi::bind(&MyActor::f, obj.get(), TOTAL, finished));
    for (int i = 0; i < 5; ++i)
      prom.future().then(qi::bind(&MyActor::f, obj.get(), TOTAL, finished));
    for (int i = 0; i < 50; ++i)
      signal.connect(&MyActor::f, obj.get(), _1, finished);
    for (int i = 0; i < 50; ++i)
      aobj.connect("sig", boost::function<void(int)>(obj->strand()->schedulerFor(boost::bind(&MyActor::f, obj, _1, finished))));

    per.start();
    for (int i = 0; i < 25; ++i)
      aobj.async<void>("f", TOTAL, finished);
    for (int i = 0; i < 25; ++i)
      qi::async(qi::bind(&MyActor::f, obj, TOTAL, finished));
    for (int i = 0; i < 50; ++i)
      aobj.setProperty("prop", rand());
    qi::Future<void> f = qi::async(boost::bind(chaincall, aobj, finished, TOTAL));
    prom.setValue(0);
    QI_EMIT signal(TOTAL);
    QI_EMIT obj->sig(TOTAL);
    for (int i = 0; i < 25; ++i)
      aobj.async<void>("f", TOTAL, finished);
    for (int i = 0; i < 25; ++i)
      qi::async(qi::bind(&MyActor::f, obj, TOTAL, finished));
    f.wait();
    finished.future().wait();
  }
  ASSERT_LT(TOTAL, callcount);
}

TEST(TestStrand, FutureThenActorCancel)
{
  callcount = 0;
  {
    boost::shared_ptr<MyActor> obj(new MyActor);
    qi::AnyObject aobj(obj);

    qi::Promise<void> finished;

    qi::Promise<int> prom(qi::PromiseNoop<int>);
    qi::Future<int> masterFut = prom.future().thenR<int>(&MyActor::f, obj, _1, finished);
    masterFut.cancel();
    ASSERT_TRUE(prom.isCancelRequested());
    prom.setValue(0);
    ASSERT_EQ(42, masterFut.value());
    ASSERT_NO_THROW(finished.future().value());
  }
}

int main(int argc, char* argv[])
{
  qi::Application app(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  // better for these tests, since a task is 5ms long
  qi::os::setenv("QI_STRAND_QUANTUM_US", "50000");
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */
#include <cstdio>

#include <qi/os.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>

static class threadTest
{
public:
  inline threadTest();
  inline ~threadTest();

  void run()
  {
    while (_glInit)
    {
      printTest();
      qi::os::sleep(1);
    }

    std::cout << "Stop running" << std::endl;
    fflush(stdout);
  }

  void printTest()
  {
    std::cout << "Running..." << std::endl;
    fflush(stdout);
  }

public:
  bool                       _glInit;
  boost::thread              _glThread;
  boost::mutex               _glLock;
  boost::condition_variable  _glCond;
} threadGolbal;

inline threadTest::threadTest()
{
  _glInit = true;
  _glThread = boost::thread(&threadTest::run, &threadGolbal);
  std::cout << "Creating main thread" << std::endl;
  fflush(stdout);
};

inline threadTest::~threadTest()
{
  _glInit = false;

  _glThread.interrupt();
  std::cout << "Interrupting main thread" << std::endl;
  fflush(stdout);

  _glThread.join();
  std::cout << "Joinning main thread" << std::endl;
  fflush(stdout);

  printTest();
  std::cout << "Main thread destroyed" << std::endl;
  fflush(stdout);
};

int main(int argc, char *argv[])
{
  std::cout << "Entering main function" << std::endl;
  fflush(stdout);

  qi::os::sleep(5);

  std::cout << "Leaving main function" << std::endl;
  fflush(stdout);

  exit(0);
}
<commit_msg>Fix helgrind warnings in test_thread<commit_after>/*
 * Copyright (c) 2012-2015 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <atomic>
#include <cstdio>
#include <mutex>

#include <qi/os.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>

struct SafeCout
{
  static std::mutex m;

  template<typename T>
  std::ostream& operator<<(const T& whatever)
  {
    std::unique_lock<std::mutex> l{m};
    auto& o = std::cout << whatever;
    fflush(stdout);
    return o;
  }
} safeCout;

std::mutex SafeCout::m = {};

static class threadTest
{
public:
  inline threadTest();
  inline ~threadTest();

  void run()
  {
    while (_glInit)
    {
      printTest();
      qi::os::sleep(1);
    }

    safeCout << "Stop running" << std::endl;
  }

  void printTest()
  {
    safeCout << "Running..." << std::endl;
  }

public:
  std::atomic<bool>          _glInit;
  boost::thread              _glThread;
} threadGlobal;

inline threadTest::threadTest()
{
  _glInit = true;
  safeCout << "Creating main thread" << std::endl;
  _glThread = boost::thread(&threadTest::run, &threadGlobal);
};

inline threadTest::~threadTest()
{
  _glInit = false;

  _glThread.interrupt();
  safeCout << "Interrupting main thread" << std::endl;

  _glThread.join();
  safeCout << "Joining main thread" << std::endl;

  printTest();
  safeCout << "Main thread destroyed" << std::endl;
};

int main(int argc, char *argv[])
{
  safeCout << "Entering main function" << std::endl;

  qi::os::sleep(5);

  safeCout << "Leaving main function" << std::endl;

  exit(0);
}
<|endoftext|>


<commit_before>/*
	don't remove the top of BOM for VC
*/
#include <cybozu/test.hpp>
#include <cybozu/fmindex.hpp>
#include <cybozu/file.hpp>
#include <cybozu/mmap.hpp>
#include <cybozu/string.hpp>
#include <set>

typedef std::set<int> Set;

std::string g_textTbl[] = {
	"",
	"abracatabra",
	"cybozuabcabcintint}}",
};

struct Init {
	Init()
	{
		std::string path = cybozu::file::GetExePath();
		size_t pos = path.find("cybozulib");
		CYBOZU_TEST_ASSERT(pos != std::string::npos);
		path = path.substr(0, pos + 9) + "/include/cybozu/fmindex.hpp";
		cybozu::Mmap mmap(path);
		g_textTbl[0].assign(mmap.get(), (size_t)mmap.size());
	}
} init;

//	f.getPrevString(out, 0, f.wm.size() - 1);

template<class FMINDEX, class STRING>
Set searchPos1(const FMINDEX& f, const STRING& key)
{
	Set ret;
	size_t begin, end;
	if (f.getRange(&begin, &end, key)) {
		while (begin != end) {
			ret.insert((int)f.convertPosition(begin));
			++begin;
		}
	}
	return ret;
}

// standard search
template<class STRING>
Set searchPos2(const STRING& text, const STRING& key)
{
	Set ret;
	size_t pos = 0;
	for (;;) {
		size_t q = text.find(key, pos);
		if (q == std::string::npos) break;
		ret.insert((int)q);
		pos = q + 1;
	}
	return ret;
}

template<class FMINDEX, class STRING>
void compareText(const FMINDEX& f, const STRING& text, const STRING *keyTbl, size_t keySize)
{
	for (size_t i = 0; i < keySize; i++) {
		const STRING& key = keyTbl[i];
		Set a = searchPos1(f, key);
		Set b = searchPos2(text, key);
		CYBOZU_TEST_EQUAL(a.size(), b.size());
		if (a.size() == b.size()) {
			size_t pos = 0;
			for (Set::const_iterator ia = a.begin(), ib = b.begin(); pos < a.size(); ++ia, ++ib, ++pos) {
				CYBOZU_TEST_EQUAL(*ia, *ib);
			}
		}
	}
	// recover string
	STRING org;
	f.getPrevString(org, 0, f.wm.size() - 1);
	CYBOZU_TEST_EQUAL(org.size(), text.size());
	CYBOZU_TEST_ASSERT(org == text);
}

template<class FMINDEX, class STRING>
void searchTest(const STRING& text, const STRING *keyTbl, size_t keySize)
{
	FMINDEX f;
	f.init(text.begin(), text.end());
	compareText(f, text, keyTbl, keySize);
	std::stringstream ss;
	f.save(ss);
	{
		FMINDEX ff;
		ff.load(ss);
		compareText(ff, text, keyTbl, keySize);
	}
}

CYBOZU_TEST_AUTO(string)
{
	static const std::string tbl[] = {
		"double", "int", "cybozu", "std", "}", "\t", "xxx",
	};
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(g_textTbl); i++) {
		searchTest<cybozu::FMindex, std::string>(g_textTbl[i], tbl, CYBOZU_NUM_OF_ARRAY(tbl));
	}
}

CYBOZU_TEST_AUTO(wstring)
{
	static const cybozu::String text(CYBOZU_STR_W("あいうえおabcあいうえおaaabあああうえabうえあいう"));
	static const cybozu::String tbl[] = {
		CYBOZU_STR_W("あいう"),
		CYBOZU_STR_W("ab"),
		CYBOZU_STR_W("うえ"),
	};
	searchTest<cybozu::FMindexT<cybozu::Char>, cybozu::String>(text, tbl, CYBOZU_NUM_OF_ARRAY(tbl));
}
<commit_msg>disable warning about end<commit_after>/*
	don't remove the top of BOM for VC
*/
#include <cybozu/test.hpp>
#include <cybozu/fmindex.hpp>
#include <cybozu/file.hpp>
#include <cybozu/mmap.hpp>
#include <cybozu/string.hpp>
#include <set>

typedef std::set<int> Set;

std::string g_textTbl[] = {
	"",
	"abracatabra",
	"cybozuabcabcintint}}",
};

struct Init {
	Init()
	{
		std::string path = cybozu::file::GetExePath();
		size_t pos = path.find("cybozulib");
		CYBOZU_TEST_ASSERT(pos != std::string::npos);
		path = path.substr(0, pos + 9) + "/include/cybozu/fmindex.hpp";
		cybozu::Mmap mmap(path);
		g_textTbl[0].assign(mmap.get(), (size_t)mmap.size());
	}
} init;

//	f.getPrevString(out, 0, f.wm.size() - 1);

template<class FMINDEX, class STRING>
Set searchPos1(const FMINDEX& f, const STRING& key)
{
	Set ret;
	size_t begin, end = 0;
	if (f.getRange(&begin, &end, key)) {
		while (begin != end) {
			ret.insert((int)f.convertPosition(begin));
			++begin;
		}
	}
	return ret;
}

// standard search
template<class STRING>
Set searchPos2(const STRING& text, const STRING& key)
{
	Set ret;
	size_t pos = 0;
	for (;;) {
		size_t q = text.find(key, pos);
		if (q == std::string::npos) break;
		ret.insert((int)q);
		pos = q + 1;
	}
	return ret;
}

template<class FMINDEX, class STRING>
void compareText(const FMINDEX& f, const STRING& text, const STRING *keyTbl, size_t keySize)
{
	for (size_t i = 0; i < keySize; i++) {
		const STRING& key = keyTbl[i];
		Set a = searchPos1(f, key);
		Set b = searchPos2(text, key);
		CYBOZU_TEST_EQUAL(a.size(), b.size());
		if (a.size() == b.size()) {
			size_t pos = 0;
			for (Set::const_iterator ia = a.begin(), ib = b.begin(); pos < a.size(); ++ia, ++ib, ++pos) {
				CYBOZU_TEST_EQUAL(*ia, *ib);
			}
		}
	}
	// recover string
	STRING org;
	f.getPrevString(org, 0, f.wm.size() - 1);
	CYBOZU_TEST_EQUAL(org.size(), text.size());
	CYBOZU_TEST_ASSERT(org == text);
}

template<class FMINDEX, class STRING>
void searchTest(const STRING& text, const STRING *keyTbl, size_t keySize)
{
	FMINDEX f;
	f.init(text.begin(), text.end());
	compareText(f, text, keyTbl, keySize);
	std::stringstream ss;
	f.save(ss);
	{
		FMINDEX ff;
		ff.load(ss);
		compareText(ff, text, keyTbl, keySize);
	}
}

CYBOZU_TEST_AUTO(string)
{
	static const std::string tbl[] = {
		"double", "int", "cybozu", "std", "}", "\t", "xxx",
	};
	for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(g_textTbl); i++) {
		searchTest<cybozu::FMindex, std::string>(g_textTbl[i], tbl, CYBOZU_NUM_OF_ARRAY(tbl));
	}
}

CYBOZU_TEST_AUTO(wstring)
{
	static const cybozu::String text(CYBOZU_STR_W("あいうえおabcあいうえおaaabあああうえabうえあいう"));
	static const cybozu::String tbl[] = {
		CYBOZU_STR_W("あいう"),
		CYBOZU_STR_W("ab"),
		CYBOZU_STR_W("うえ"),
	};
	searchTest<cybozu::FMindexT<cybozu::Char>, cybozu::String>(text, tbl, CYBOZU_NUM_OF_ARRAY(tbl));
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2015 Dims dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "common/manageNetwork.h"
#include "common/actionHandler.h"

#include "monitor/recognizeNetworkAction.h"
#include "monitor/connectNodeAction.h"
#include "monitor/filters.h"

#include <boost/statechart/state.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>

namespace monitor
{

struct CGetDnsInfo : boost::statechart::state< CGetDnsInfo, CRecognizeNetworkAction >
{
	CGetDnsInfo( my_context ctx ) : my_base( ctx )
	{
		// search for  seeder  action
		std::vector<CAddress> vAdd;

		common::CManageNetwork::getInstance()->getIpsFromSeed( vAdd );

		if ( !vAdd.empty() )
		{
			BOOST_FOREACH( CAddress address, vAdd )
			{
				context< CRecognizeNetworkAction >().dropRequests();
				context< CRecognizeNetworkAction >().addRequest(
							new common::CScheduleActionRequest< common::CMonitorTypes >(
								new CConnectNodeAction( address )
								, new CMediumClassFilter( common::CMediumKinds::Schedule) ) );
			}
		}
		else
		{
			common::CManageNetwork::getInstance()->getSeedIps( vAdd );

			// let know seed about our existence
			BOOST_FOREACH( CAddress address, vAdd )
			{
				context< CRecognizeNetworkAction >().dropRequests();
				context< CRecognizeNetworkAction >().addRequest(
							new common::CScheduleActionRequest< common::CMonitorTypes >(
								new CConnectNodeAction( address )
								, new CMediumClassFilter( common::CMediumKinds::Schedule) ) );
			}
		}
	}

	boost::statechart::result react( common::CNetworkInfoEvent const & _networkInfoEvent )
	{
		//return transit< CDetermineRoleConnecting >();
		return discard_event();
	}

	typedef boost::mpl::list<
	boost::statechart::custom_reaction< common::CNetworkInfoEvent >
	> reactions;

};

CRecognizeNetworkAction::CRecognizeNetworkAction()
{
	initiate();
}

void
CRecognizeNetworkAction::accept( common::CSetResponseVisitor< common::CMonitorTypes > & _visitor )
{
	_visitor.visit( *this );
}

}
<commit_msg>small in  monitor<commit_after>// Copyright (c) 2014-2015 Dims dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "common/manageNetwork.h"
#include "common/actionHandler.h"

#include "monitor/recognizeNetworkAction.h"
#include "monitor/connectNodeAction.h"
#include "monitor/filters.h"

#include <boost/statechart/state.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>

namespace monitor
{

struct CGetDnsInfo : boost::statechart::state< CGetDnsInfo, CRecognizeNetworkAction >
{
	CGetDnsInfo( my_context ctx ) : my_base( ctx )
	{
		// search for  seeder  action
		std::vector<CAddress> vAdd;

		common::CManageNetwork::getInstance()->getIpsFromSeed( vAdd );

		if ( !vAdd.empty() )
		{
			BOOST_FOREACH( CAddress address, vAdd )
			{
				context< CRecognizeNetworkAction >().dropRequests();
				context< CRecognizeNetworkAction >().addRequest(
							new common::CScheduleActionRequest< common::CMonitorTypes >(
								new CConnectNodeAction( address )
								, new CMediumClassFilter( common::CMediumKinds::Schedule) ) );
			}
		}
		else
		{
			common::CManageNetwork::getInstance()->getSeedIps( vAdd );

			// let know seed about our existence
			BOOST_FOREACH( CAddress address, vAdd )
			{
				context< CRecognizeNetworkAction >().dropRequests();
				context< CRecognizeNetworkAction >().addRequest(
							new common::CScheduleActionRequest< common::CMonitorTypes >(
								new CConnectNodeAction( address )
								, new CMediumClassFilter( common::CMediumKinds::Schedule) ) );
			}
		}
	}

	boost::statechart::result react( common::CNetworkInfoEvent const & _networkInfoEvent )
	{
		context< CRecognizeNetworkAction >().setExit();
		return discard_event();
	}

	typedef boost::mpl::list<
	boost::statechart::custom_reaction< common::CNetworkInfoEvent >
	> reactions;

};

CRecognizeNetworkAction::CRecognizeNetworkAction()
{
	initiate();
}

void
CRecognizeNetworkAction::accept( common::CSetResponseVisitor< common::CMonitorTypes > & _visitor )
{
	_visitor.visit( *this );
}

}
<|endoftext|>


<commit_before><commit_msg>`Font2D`: `screen_width`, `screen_height`, `font_texture_file_format`.<commit_after><|endoftext|>


<commit_before><commit_msg>A few more bitmap fixes for the GL build Review URL: http://codereview.chromium.org/149684<commit_after><|endoftext|>


<commit_before>/*
Copyright (c) 2015-2017 by the parties listed in the AUTHORS file.
All rights reserved.  Use of this source code is governed by
a BSD-style license that can be found in the LICENSE file.
*/

#ifndef timing_manager_hpp_
#define timing_manager_hpp_

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

#include <unordered_map>
#include <deque>
#include <string>
#include "timer.hpp"

#include <mpi.h>

#ifdef _OPENMP
#   include <omp.h>
#endif

#include <cereal/cereal.hpp>
#include <cereal/types/deque.hpp>
#include <cereal/access.hpp>
#include <cereal/types/unordered_map.hpp>
#include <cereal/types/chrono.hpp>
#include <cereal/archives/adapters.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/archives/portable_binary.hpp>
#include <cereal/archives/xml.hpp>

namespace toast
{
namespace util
{

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

inline bool mpi_is_initialized()
{
    int32_t _init = 0;
    MPI_Initialized(&_init);
    return (_init != 0) ? true : false;
}

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

inline int32_t mpi_rank()
{
    int32_t _rank = 0;
    if(mpi_is_initialized())
        MPI_Comm_rank(MPI_COMM_WORLD, &_rank);
    return std::max(_rank, (int32_t) 0);
}

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

inline int32_t mpi_size()
{
    int32_t _size = 1;
    if(mpi_is_initialized())
        MPI_Comm_size(MPI_COMM_WORLD, &_size);
    return std::max(_size, (int32_t) 1);
}

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

inline int32_t get_max_threads()
{
#ifdef _OPENMP
    return omp_get_max_threads();
#else
    return 1;
#endif
}

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

struct timer_tuple : public std::tuple<uint64_t, uint64_t, std::string,
                                       toast::util::timer&>
{
    typedef std::string                                     string_t;
    typedef toast::util::timer                              toast_timer_t;
    typedef uint64_t                                        first_type;
    typedef uint64_t                                        second_type;
    typedef string_t                                        third_type;
    typedef toast_timer_t&                                  fourth_type;
    typedef std::tuple<uint64_t, uint64_t, string_t,
                       toast_timer_t&>                      base_type;

    timer_tuple(const base_type& _data) : base_type(_data) { }
    timer_tuple(first_type _b, second_type _s, third_type _t, fourth_type _f)
    : base_type(_b, _s, _t, _f) { }

    timer_tuple& operator=(const base_type& rhs)
    {
        if(this == &rhs)
            return *this;
        base_type::operator =(rhs);
        return *this;
    }

    first_type& key() { return std::get<0>(*this); }
    const first_type& key() const { return std::get<0>(*this); }

    second_type& level() { return std::get<1>(*this); }
    const second_type& level() const { return std::get<1>(*this); }

    third_type tag() { return std::get<2>(*this); }
    const third_type tag() const { return std::get<2>(*this); }

    fourth_type timer() { return std::get<3>(*this); }
    const fourth_type timer() const { return std::get<3>(*this); }

    // serialization function
    template <typename Archive> void
    serialize(Archive& ar, const unsigned int /*version*/)
    {
        ar(cereal::make_nvp("timer.key", std::get<0>(*this)),
           cereal::make_nvp("timer.level", std::get<1>(*this)),
           cereal::make_nvp("timer.tag", std::get<2>(*this)),
           cereal::make_nvp("timer.ref", std::get<3>(*this)));
    }
};

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

class timing_manager
{
public:
    template <typename _Key, typename _Mapped>
    using uomap = std::unordered_map<_Key, _Mapped>;

    typedef toast::util::timer                  toast_timer_t;
    typedef toast_timer_t::string_t             string_t;
    typedef timer_tuple                         timer_tuple_t;
    typedef std::deque<timer_tuple_t>           timer_list_t;
    typedef timer_list_t::iterator              iterator;
    typedef timer_list_t::const_iterator        const_iterator;
    typedef timer_list_t::size_type             size_type;
    typedef uomap<uint64_t, toast_timer_t>      timer_map_t;
    typedef toast_timer_t::ostream_t            ostream_t;
    typedef toast_timer_t::ofstream_t           ofstream_t;
    typedef toast::clock_type                   clock_type;

public:
	// Constructor and Destructors
    timing_manager();
    virtual ~timing_manager();

public:
    // Public static functions
    static timing_manager* instance();
    static void write_json(const string_t& _fname);

public:
    // Public member functions
    size_type size() const { return m_timer_list.size(); }
    void clear();

    toast_timer_t& timer(const string_t& key,
                         const string_t& tag = "cxx",
                         int32_t ncount = 0,
                         int32_t nhash = 0);

    toast_timer_t& at(size_t i) { return m_timer_list.at(i).timer(); }

    // time a function with a return type and no arguments
    template <typename _Ret, typename _Func>
    _Ret time(const string_t& key, _Func);

    // time a function with a return type and arguments
    template <typename _Ret, typename _Func, typename... _Args>
    _Ret time(const string_t& key, _Func, _Args...);

    // time a function with no return type and no arguments
    template <typename _Func>
    void time(const string_t& key, _Func);

    // time a function with no return type and arguments
    template <typename _Func, typename... _Args>
    void time(const string_t& key, _Func, _Args...);

    // serialization function
    template <typename Archive> void
    serialize(Archive& ar, const unsigned int /*version*/);

    // iteration of timers
    iterator        begin()         { return m_timer_list.begin(); }
    const_iterator  begin() const   { return m_timer_list.cbegin(); }
    const_iterator  cbegin() const  { return m_timer_list.cbegin(); }

    iterator        end()           { return m_timer_list.end(); }
    const_iterator  end() const     { return m_timer_list.cend(); }
    const_iterator  cend() const    { return m_timer_list.cend(); }

    void report() const;
    void set_output_stream(ostream_t&);
    void set_output_stream(const string_t&);

protected:
    inline uint64_t string_hash(const string_t&) const;

private:
    // Private functions
    ofstream_t* get_ofstream(ostream_t* m_os) const;
    void report(ostream_t*) const;

private:
	// Private variables
    static timing_manager*   fgInstance;
    // hashed string map for fast lookup
    timer_map_t             m_timer_map;
    // ordered list for output (outputs in order of timer instantiation)
    timer_list_t            m_timer_list;
    // output stream for total timing report
    ostream_t*              m_report;
};

//----------------------------------------------------------------------------//
inline void
timing_manager::clear()
{
    m_timer_list.clear();
    m_timer_map.clear();
    details::base_timer::get_instance_count() = 0;
    details::base_timer::get_instance_hash() = 0;
}
//----------------------------------------------------------------------------//
template <typename _Ret, typename _Func>
inline _Ret
timing_manager::time(const string_t& key, _Func func)
{
    toast_timer_t& _t = this->instance()->timer(key);
    _t.start();
    _Ret _ret = func();
    _t.stop();
    return _ret;
}
//----------------------------------------------------------------------------//
template <typename _Ret, typename _Func, typename... _Args>
inline _Ret
timing_manager::time(const string_t& key, _Func func, _Args... args)
{
    toast_timer_t& _t = this->instance()->timer(key);
    _t.start();
    _Ret _ret = func(args...);
    _t.stop();
    return _ret;
}
//----------------------------------------------------------------------------//
template <typename _Func>
inline void
timing_manager::time(const string_t& key, _Func func)
{
    toast_timer_t& _t = this->instance()->timer(key);
    _t.start();
    func();
    _t.stop();
}
//----------------------------------------------------------------------------//
template <typename _Func, typename... _Args>
inline void
timing_manager::time(const string_t& key, _Func func, _Args... args)
{
    toast_timer_t& _t = this->instance()->timer(key);
    _t.start();
    func(args...);
    _t.stop();
}
//----------------------------------------------------------------------------//
template <typename Archive>
inline void
timing_manager::serialize(Archive& ar, const unsigned int /*version*/)
{
    uint32_t omp_nthreads = get_max_threads();
    ar(cereal::make_nvp("omp_concurrency", omp_nthreads));
    ar(cereal::make_nvp("timers", m_timer_list));
}
//----------------------------------------------------------------------------//
inline uint64_t
timing_manager::string_hash(const string_t& str) const
{
    //return std::hash<string_t>()(str);
    // computes the hash of an employee using a variant
    // of the Fowler-Noll-Vo hash function
    uint64_t result = 2166136261;

    for(const auto& itr : str)
        result = (result * 16777619) ^ itr;
    return result ^ str.length();
}
//----------------------------------------------------------------------------//

} // namespace util

} // namespace toast

#endif // timing_manager_hpp_
<commit_msg>Replaced custom string hashing with STL string hashing<commit_after>/*
Copyright (c) 2015-2017 by the parties listed in the AUTHORS file.
All rights reserved.  Use of this source code is governed by
a BSD-style license that can be found in the LICENSE file.
*/

#ifndef timing_manager_hpp_
#define timing_manager_hpp_

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

#include <unordered_map>
#include <deque>
#include <string>
#include "timer.hpp"

#include <mpi.h>

#ifdef _OPENMP
#   include <omp.h>
#endif

#include <cereal/cereal.hpp>
#include <cereal/types/deque.hpp>
#include <cereal/access.hpp>
#include <cereal/types/unordered_map.hpp>
#include <cereal/types/chrono.hpp>
#include <cereal/archives/adapters.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/archives/portable_binary.hpp>
#include <cereal/archives/xml.hpp>

namespace toast
{
namespace util
{

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

inline bool mpi_is_initialized()
{
    int32_t _init = 0;
    MPI_Initialized(&_init);
    return (_init != 0) ? true : false;
}

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

inline int32_t mpi_rank()
{
    int32_t _rank = 0;
    if(mpi_is_initialized())
        MPI_Comm_rank(MPI_COMM_WORLD, &_rank);
    return std::max(_rank, (int32_t) 0);
}

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

inline int32_t mpi_size()
{
    int32_t _size = 1;
    if(mpi_is_initialized())
        MPI_Comm_size(MPI_COMM_WORLD, &_size);
    return std::max(_size, (int32_t) 1);
}

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

inline int32_t get_max_threads()
{
#ifdef _OPENMP
    return omp_get_max_threads();
#else
    return 1;
#endif
}

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

struct timer_tuple : public std::tuple<uint64_t, uint64_t, std::string,
                                       toast::util::timer&>
{
    typedef std::string                                     string_t;
    typedef toast::util::timer                              toast_timer_t;
    typedef uint64_t                                        first_type;
    typedef uint64_t                                        second_type;
    typedef string_t                                        third_type;
    typedef toast_timer_t&                                  fourth_type;
    typedef std::tuple<uint64_t, uint64_t, string_t,
                       toast_timer_t&>                      base_type;

    timer_tuple(const base_type& _data) : base_type(_data) { }
    timer_tuple(first_type _b, second_type _s, third_type _t, fourth_type _f)
    : base_type(_b, _s, _t, _f) { }

    timer_tuple& operator=(const base_type& rhs)
    {
        if(this == &rhs)
            return *this;
        base_type::operator =(rhs);
        return *this;
    }

    first_type& key() { return std::get<0>(*this); }
    const first_type& key() const { return std::get<0>(*this); }

    second_type& level() { return std::get<1>(*this); }
    const second_type& level() const { return std::get<1>(*this); }

    third_type tag() { return std::get<2>(*this); }
    const third_type tag() const { return std::get<2>(*this); }

    fourth_type timer() { return std::get<3>(*this); }
    const fourth_type timer() const { return std::get<3>(*this); }

    // serialization function
    template <typename Archive> void
    serialize(Archive& ar, const unsigned int /*version*/)
    {
        ar(cereal::make_nvp("timer.key", std::get<0>(*this)),
           cereal::make_nvp("timer.level", std::get<1>(*this)),
           cereal::make_nvp("timer.tag", std::get<2>(*this)),
           cereal::make_nvp("timer.ref", std::get<3>(*this)));
    }
};

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

class timing_manager
{
public:
    template <typename _Key, typename _Mapped>
    using uomap = std::unordered_map<_Key, _Mapped>;

    typedef toast::util::timer                  toast_timer_t;
    typedef toast_timer_t::string_t             string_t;
    typedef timer_tuple                         timer_tuple_t;
    typedef std::deque<timer_tuple_t>           timer_list_t;
    typedef timer_list_t::iterator              iterator;
    typedef timer_list_t::const_iterator        const_iterator;
    typedef timer_list_t::size_type             size_type;
    typedef uomap<uint64_t, toast_timer_t>      timer_map_t;
    typedef toast_timer_t::ostream_t            ostream_t;
    typedef toast_timer_t::ofstream_t           ofstream_t;
    typedef toast::clock_type                   clock_type;

public:
	// Constructor and Destructors
    timing_manager();
    virtual ~timing_manager();

public:
    // Public static functions
    static timing_manager* instance();
    static void write_json(const string_t& _fname);

public:
    // Public member functions
    size_type size() const { return m_timer_list.size(); }
    void clear();

    toast_timer_t& timer(const string_t& key,
                         const string_t& tag = "cxx",
                         int32_t ncount = 0,
                         int32_t nhash = 0);

    toast_timer_t& at(size_t i) { return m_timer_list.at(i).timer(); }

    // time a function with a return type and no arguments
    template <typename _Ret, typename _Func>
    _Ret time(const string_t& key, _Func);

    // time a function with a return type and arguments
    template <typename _Ret, typename _Func, typename... _Args>
    _Ret time(const string_t& key, _Func, _Args...);

    // time a function with no return type and no arguments
    template <typename _Func>
    void time(const string_t& key, _Func);

    // time a function with no return type and arguments
    template <typename _Func, typename... _Args>
    void time(const string_t& key, _Func, _Args...);

    // serialization function
    template <typename Archive> void
    serialize(Archive& ar, const unsigned int /*version*/);

    // iteration of timers
    iterator        begin()         { return m_timer_list.begin(); }
    const_iterator  begin() const   { return m_timer_list.cbegin(); }
    const_iterator  cbegin() const  { return m_timer_list.cbegin(); }

    iterator        end()           { return m_timer_list.end(); }
    const_iterator  end() const     { return m_timer_list.cend(); }
    const_iterator  cend() const    { return m_timer_list.cend(); }

    void report() const;
    void set_output_stream(ostream_t&);
    void set_output_stream(const string_t&);

protected:
    inline uint64_t string_hash(const string_t&) const;

private:
    // Private functions
    ofstream_t* get_ofstream(ostream_t* m_os) const;
    void report(ostream_t*) const;

private:
	// Private variables
    static timing_manager*   fgInstance;
    // hashed string map for fast lookup
    timer_map_t             m_timer_map;
    // ordered list for output (outputs in order of timer instantiation)
    timer_list_t            m_timer_list;
    // output stream for total timing report
    ostream_t*              m_report;
};

//----------------------------------------------------------------------------//
inline void
timing_manager::clear()
{
    m_timer_list.clear();
    m_timer_map.clear();
    details::base_timer::get_instance_count() = 0;
    details::base_timer::get_instance_hash() = 0;
}
//----------------------------------------------------------------------------//
template <typename _Ret, typename _Func>
inline _Ret
timing_manager::time(const string_t& key, _Func func)
{
    toast_timer_t& _t = this->instance()->timer(key);
    _t.start();
    _Ret _ret = func();
    _t.stop();
    return _ret;
}
//----------------------------------------------------------------------------//
template <typename _Ret, typename _Func, typename... _Args>
inline _Ret
timing_manager::time(const string_t& key, _Func func, _Args... args)
{
    toast_timer_t& _t = this->instance()->timer(key);
    _t.start();
    _Ret _ret = func(args...);
    _t.stop();
    return _ret;
}
//----------------------------------------------------------------------------//
template <typename _Func>
inline void
timing_manager::time(const string_t& key, _Func func)
{
    toast_timer_t& _t = this->instance()->timer(key);
    _t.start();
    func();
    _t.stop();
}
//----------------------------------------------------------------------------//
template <typename _Func, typename... _Args>
inline void
timing_manager::time(const string_t& key, _Func func, _Args... args)
{
    toast_timer_t& _t = this->instance()->timer(key);
    _t.start();
    func(args...);
    _t.stop();
}
//----------------------------------------------------------------------------//
template <typename Archive>
inline void
timing_manager::serialize(Archive& ar, const unsigned int /*version*/)
{
    uint32_t omp_nthreads = get_max_threads();
    ar(cereal::make_nvp("omp_concurrency", omp_nthreads));
    ar(cereal::make_nvp("timers", m_timer_list));
}
//----------------------------------------------------------------------------//
inline uint64_t
timing_manager::string_hash(const string_t& str) const
{
    return std::hash<string_t>()(str);
}
//----------------------------------------------------------------------------//

} // namespace util

} // namespace toast

#endif // timing_manager_hpp_
<|endoftext|>


<commit_before>#include <string>
#include <tclap/CmdLine.h>

using namespace TCLAP;

int main(int argc, char** argv)
{
	// Wrap everything in a try block.  Do this every time,
	// because exceptions will be thrown for problems.
	try {

	// Define the command line object.
	CmdLine cmd("Command description message. This is a long multi-line message meant to test line wrapping.  This is more text that doesn't really do anything besides take up lots of space that otherwise might be used for something real.  That should be enough, don't you think?", ' ', "0.9");

	vector<string> allowed;
	allowed.push_back("homer");
	allowed.push_back("marge");
	allowed.push_back("bart");
	allowed.push_back("lisa");
	allowed.push_back("maggie");

	MultiArg<string> nameArg("n","name","Name to print. This is a long, nonsensical message to test line wrapping.  Hopefully it works.",true,allowed);
	cmd.add( nameArg );

	vector<int> iallowed;
	iallowed.push_back(1);
	iallowed.push_back(2);
	iallowed.push_back(3);

	UnlabeledMultiArg<int> intArg("times","Number of times to print",iallowed);
	cmd.add( intArg );

	// Parse the args.
	cmd.parse( argc, argv );

	// Get the value parsed by each arg.
	vector<int> num = intArg.getValue();

	for ( unsigned int i = 0; i < num.size(); i++ )
		cout << "Got num " << num[i] << endl;

	vector<string> name = nameArg.getValue();

	for ( unsigned int i = 0; i < name.size(); i++ )
		cout << "Got name " << name[i] << endl;

	} catch (ArgException e)  // catch any exceptions
	{ cerr << "error: " << e.error() << " for arg " << e.argId() << endl; }
}

<commit_msg>added more args to better test output printing<commit_after>#include <string>
#include <tclap/CmdLine.h>

using namespace TCLAP;
using namespace std;

int main(int argc, char** argv)
{
	// Wrap everything in a try block.  Do this every time,
	// because exceptions will be thrown for problems.
	try {

	// Define the command line object.
	CmdLine cmd("Command description message. This is a long multi-line message meant to test line wrapping.  This is more text that doesn't really do anything besides take up lots of space that otherwise might be used for something real.  That should be enough, don't you think?", ' ', "0.9");

	vector<string> allowed;
	allowed.push_back("homer");
	allowed.push_back("marge");
	allowed.push_back("bart");
	allowed.push_back("lisa");
	allowed.push_back("maggie");

	MultiArg<string> nameArg("n","name","Name to print. This is a long, nonsensical message to test line wrapping.  Hopefully it works.",true,allowed);
	cmd.add( nameArg );

	vector<int> iallowed;
	iallowed.push_back(1);
	iallowed.push_back(2);
	iallowed.push_back(3);

	UnlabeledMultiArg<int> intArg("times","Number of times to print",iallowed);
	cmd.add( intArg );

	// Ignore the names and comments!  These  args mean nothing (to this
	// program) and are here solely to take up space.
    ValueArg<int> gapCreate("f","gapCreate", "The cost of creating a gap",
	                                 false, -10, "negative int");
	cmd.add( gapCreate );

	ValueArg<int> gapExtend("g","gapExtend",
		"The cost for each extension of a gap", false, -2, "negative int");
	cmd.add( gapExtend );

	SwitchArg dna("d","isDna","The input sequences are DNA", false);
	cmd.add( dna );

	ValueArg<string> scoringMatrixName("s","scoringMatrix",
		"Scoring Matrix name", false,"BLOSUM50","name string");
	cmd.add( scoringMatrixName );

	ValueArg<string> seq1Filename ("f","filename1",
		"Sequence 1 filename (FASTA format)", false,"","filename");
	cmd.add( seq1Filename );

	ValueArg<string> seq2Filename ("F","filename2",
		"Sequence 2 filename (FASTA format)", false,"","filename");
	cmd.add( seq2Filename );

	ValueArg<float> lowerBound("b","lowerBound", "lower percentage bound",
		false,1.0,"float lte 1");
	cmd.add( lowerBound );

	ValueArg<float> upperBound("u","upperBound", "upper percentage bound",
		false,1.0,"float lte 1");
	cmd.add( upperBound );

	ValueArg<int> limit("l","limit","Max number of alignments allowed",
		false, 1000,"int");
	cmd.add( limit );

	// Parse the args.
	cmd.parse( argc, argv );

	// Get the value parsed by each arg.
	vector<int> num = intArg.getValue();

	for ( unsigned int i = 0; i < num.size(); i++ )
		cout << "Got num " << num[i] << endl;

	vector<string> name = nameArg.getValue();

	for ( unsigned int i = 0; i < name.size(); i++ )
		cout << "Got name " << name[i] << endl;

	} catch (ArgException e)  // catch any exceptions
	{ cerr << "error: " << e.error() << " for arg " << e.argId() << endl; }
}

<|endoftext|>


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

#ifndef REALM_UTIL_COMPILER_HPP
#define REALM_UTIL_COMPILER_HPP

#ifdef __has_cpp_attribute
#define REALM_HAS_CCP_ATTRIBUTE(attr) __has_cpp_attribute(attr)
#else
#define REALM_HAS_CCP_ATTRIBUTE(attr) 0
#endif

#if REALM_HAS_CCP_ATTRIBUTE(clang::fallthrough)
#define REALM_FALLTHROUGH [[clang::fallthrough]]
#else
#define REALM_FALLTHROUGH
#endif

#endif // REALM_UTIL_COMPILER_HPP
<commit_msg>Fix a typo in the name of a #define.<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_UTIL_COMPILER_HPP
#define REALM_UTIL_COMPILER_HPP

#ifdef __has_cpp_attribute
#define REALM_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr)
#else
#define REALM_HAS_CPP_ATTRIBUTE(attr) 0
#endif

#if REALM_HAS_CPP_ATTRIBUTE(clang::fallthrough)
#define REALM_FALLTHROUGH [[clang::fallthrough]]
#else
#define REALM_FALLTHROUGH
#endif

#endif // REALM_UTIL_COMPILER_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2015 cpichard.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#if HAVE_ALEMBIC

#include "AlembicImporter.hpp"

#include <Alembic/AbcGeom/All.h>
#include <Alembic/AbcCoreFactory/All.h>

using namespace Alembic::Abc;
namespace AbcG = Alembic::AbcGeom;
using namespace AbcG;

namespace openMVG {
namespace dataio {

// Top down insertion of 3d objects

void AlembicImporter::visitObject(IObject iObj, M44d mat, sfm::SfM_Data &sfmdata, sfm::ESfM_Data flags_part)
{
  using namespace openMVG::geometry;
  using namespace openMVG::cameras;
  using namespace openMVG::sfm;

  const MetaData& md = iObj.getMetaData();
  if(IPoints::matches(md) && (flags_part & sfm::ESfM_Data::STRUCTURE))
  {
    IPoints points(iObj, kWrapExisting);
    IPointsSchema ms = points.getSchema();
    P3fArraySamplePtr positions = ms.getValue().getPositions();

    //@todo use positions->get() and positions->size());
    //@todo put the points somewhere...
  }
  else if(IXform::matches(md))
  {
    IXform xform(iObj, kWrapExisting);
    XformSample xs;
    xform.getSchema().get(xs);
    mat *= xs.getMatrix();
  }
  else if(ICamera::matches(md) && (flags_part & sfm::ESfM_Data::EXTRINSICS))
  {
    // OpenMVG Camera
    Mat3 cam_r;
    cam_r(0,0) = mat[0][0];
    cam_r(0,1) = mat[0][1];
    cam_r(0,2) = mat[0][2];
    cam_r(1,0) = mat[1][0];
    cam_r(1,1) = mat[1][1];
    cam_r(1,2) = mat[1][2];
    cam_r(2,0) = mat[2][0];
    cam_r(2,1) = mat[2][1];
    cam_r(2,2) = mat[2][2];
    Vec3 cam_t;
    cam_t(0) = mat[3][0];
    cam_t(1) = mat[3][1];
    cam_t(2) = mat[3][2];
    Pose3 pose(cam_r, cam_t);

    ICamera camera(iObj, kWrapExisting);
    ICameraSchema cs = camera.getSchema();
    CameraSample camSample = cs.getValue();

    double width = camSample.getHorizontalAperture(); // TODO
    double height = camSample.getVerticalAperture();

    Pinhole_Intrinsic intrinsic(
      width, height,
      camSample.getFocalLength(), // TODO: pix
      camSample.getHorizontalFilmOffset(), camSample.getVerticalFilmOffset());

    IndexT id_view = sfmdata.GetViews().size(); // TODO real index
    IndexT id_pose = sfmdata.GetPoses().size();
    IndexT id_intrinsics = sfmdata.GetIntrinsics().size();

    const std::string objectName = iObj.getName();

    sfmdata.views.emplace(id_view, std::make_shared<View>(objectName, id_view, id_pose, id_intrinsics, width, height));
    sfmdata.poses.emplace(id_pose, pose);
    sfmdata.intrinsics.emplace(id_intrinsics, std::make_shared<Pinhole_Intrinsic>(intrinsic));
  }

  // Recurse
  for(size_t i = 0; i < iObj.getNumChildren(); i++)
  {
    visitObject(iObj.getChild(i), mat, sfmdata, flags_part);
  }
}

AlembicImporter::AlembicImporter(const std::string &filename)
{
  Alembic::AbcCoreFactory::IFactory factory;
  Alembic::AbcCoreFactory::IFactory::CoreType coreType;
  Abc::IArchive archive = factory.getArchive(filename, coreType);

  // TODO : test if archive is correctly opened
  _rootEntity = archive.getTop();
}

void AlembicImporter::populate(sfm::SfM_Data &sfmdata, sfm::ESfM_Data flags_part)
{
  // TODO : handle the case where the archive wasn't correctly opened
  M44d xformMat;
  visitObject(_rootEntity, xformMat, sfmdata, flags_part);

  // TODO: fusion of common intrinsics
}

} // namespace data_io
} // namespace openMVG
#endif // WITH_ALEMBIC

<commit_msg>[alembic] remove 'camera_' prefix if exists<commit_after>// Copyright (c) 2015 cpichard.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#if HAVE_ALEMBIC

#include "AlembicImporter.hpp"

#include <Alembic/AbcGeom/All.h>
#include <Alembic/AbcCoreFactory/All.h>

using namespace Alembic::Abc;
namespace AbcG = Alembic::AbcGeom;
using namespace AbcG;

namespace openMVG {
namespace dataio {

// Top down insertion of 3d objects

void AlembicImporter::visitObject(IObject iObj, M44d mat, sfm::SfM_Data &sfmdata, sfm::ESfM_Data flags_part)
{
  using namespace openMVG::geometry;
  using namespace openMVG::cameras;
  using namespace openMVG::sfm;

  const MetaData& md = iObj.getMetaData();
  if(IPoints::matches(md) && (flags_part & sfm::ESfM_Data::STRUCTURE))
  {
    IPoints points(iObj, kWrapExisting);
    IPointsSchema ms = points.getSchema();
    P3fArraySamplePtr positions = ms.getValue().getPositions();

    //@todo use positions->get() and positions->size());
    //@todo put the points somewhere...
  }
  else if(IXform::matches(md))
  {
    IXform xform(iObj, kWrapExisting);
    XformSample xs;
    xform.getSchema().get(xs);
    mat *= xs.getMatrix();
  }
  else if(ICamera::matches(md) && (flags_part & sfm::ESfM_Data::EXTRINSICS))
  {
    // OpenMVG Camera
    Mat3 cam_r;
    cam_r(0,0) = mat[0][0];
    cam_r(0,1) = mat[0][1];
    cam_r(0,2) = mat[0][2];
    cam_r(1,0) = mat[1][0];
    cam_r(1,1) = mat[1][1];
    cam_r(1,2) = mat[1][2];
    cam_r(2,0) = mat[2][0];
    cam_r(2,1) = mat[2][1];
    cam_r(2,2) = mat[2][2];
    Vec3 cam_t;
    cam_t(0) = mat[3][0];
    cam_t(1) = mat[3][1];
    cam_t(2) = mat[3][2];
    Pose3 pose(cam_r, cam_t);

    ICamera camera(iObj, kWrapExisting);
    ICameraSchema cs = camera.getSchema();
    CameraSample camSample = cs.getValue();

    double width = camSample.getHorizontalAperture(); // TODO
    double height = camSample.getVerticalAperture();

    Pinhole_Intrinsic intrinsic(
      width, height,
      camSample.getFocalLength(), // TODO: pix
      camSample.getHorizontalFilmOffset(), camSample.getVerticalFilmOffset());

    IndexT id_view = sfmdata.GetViews().size(); // TODO real index
    IndexT id_pose = sfmdata.GetPoses().size();
    IndexT id_intrinsics = sfmdata.GetIntrinsics().size();

    std::string objectName = iObj.getName();
    // For readability in exporter we add a prefix 'camera_' for each view
    if(objectName.substr(0,7) == "camera_")
      objectName = objectName.substr(7);

    sfmdata.views.emplace(id_view, std::make_shared<View>(objectName, id_view, id_pose, id_intrinsics, width, height));
    sfmdata.poses.emplace(id_pose, pose);
    sfmdata.intrinsics.emplace(id_intrinsics, std::make_shared<Pinhole_Intrinsic>(intrinsic));
  }

  // Recurse
  for(size_t i = 0; i < iObj.getNumChildren(); i++)
  {
    visitObject(iObj.getChild(i), mat, sfmdata, flags_part);
  }
}

AlembicImporter::AlembicImporter(const std::string &filename)
{
  Alembic::AbcCoreFactory::IFactory factory;
  Alembic::AbcCoreFactory::IFactory::CoreType coreType;
  Abc::IArchive archive = factory.getArchive(filename, coreType);

  // TODO : test if archive is correctly opened
  _rootEntity = archive.getTop();
}

void AlembicImporter::populate(sfm::SfM_Data &sfmdata, sfm::ESfM_Data flags_part)
{
  // TODO : handle the case where the archive wasn't correctly opened
  M44d xformMat;
  visitObject(_rootEntity, xformMat, sfmdata, flags_part);

  // TODO: fusion of common intrinsics
}

} // namespace data_io
} // namespace openMVG
#endif // WITH_ALEMBIC

<|endoftext|>