<commit_before>//
// Copyright (c) 2015, Microsoft Corporation
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//

#include "pch.h"

#include <sstream>
#include "BridgeUtils.h"
#include "DeviceMain.h"
#include "DeviceSignal.h"
#include "AllJoynHelper.h"

using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation::Collections;
using namespace Windows::Foundation;

using namespace BridgeRT;
using namespace std;

DeviceSignal::DeviceSignal()
    : m_adapterSignal(nullptr)
{
}

DeviceSignal::~DeviceSignal()
{
}

QStatus DeviceSignal::Initialize(_In_ DeviceMain *parent, _In_ IAdapterSignal ^adapterSignal)
{
    QStatus status = ER_OK;

    // sanity check
    if (nullptr == parent)
    {
        status = ER_BAD_ARG_1;
        goto leave;
    }
    if (nullptr == adapterSignal)
    {
        status = ER_BAD_ARG_2;
        goto leave;
    }

    m_parent = parent;
    m_adapterSignal = adapterSignal;

    // build signal name
    status = SetName(m_adapterSignal->Name);
    if (ER_OK != status)
    {
        goto leave;
    }

    // build signatures and parameter list
    status = BuildSignature();
    if (ER_OK != status)
    {
        goto leave;
    }

    // add signal to interface
    status = alljoyn_interfacedescription_addsignal(m_parent->GetInterfaceDescription(),
        m_exposedName.c_str(),
        m_signature.c_str(),
        m_parameterNames.c_str(),
        0,
        nullptr);
    if (ER_OK != status)
    {
        goto leave;
    }

leave:
    return status;
}

void DeviceSignal::SendSignal()
{
    QStatus status = ER_OK;
    size_t nbOfArgs = 0;
    alljoyn_msgarg args = NULL;
    alljoyn_interfacedescription_member signalDescription;
    QCC_BOOL signalFound = QCC_FALSE;

    // create out arguments if necessary
    if (m_adapterSignal->Params->Size != 0)
    {
        args = alljoyn_msgarg_array_create(m_adapterSignal->Params->Size);
        if (NULL == args)
        {
            goto leave;
        }
    }

    // set arguments
    for (auto signalParam : m_adapterSignal->Params)
    {
        //check if the param is of type IPropertyValue
        auto propertyValue = dynamic_cast<IPropertyValue^>(signalParam->Data);
        if (nullptr == propertyValue)
        {
            //Not a property value, see if its an Object
            if (TypeCode::Object == Type::GetTypeCode(signalParam->Data->GetType()))
            {
                status = AllJoynHelper::SetMsgArgFromAdapterObject(signalParam, alljoyn_msgarg_array_element(args, nbOfArgs), m_parent);
            }
            else
            {
                goto leave;
            }
        }
        else
        {
            status = AllJoynHelper::SetMsgArg(signalParam, alljoyn_msgarg_array_element(args, nbOfArgs));
        }

        if (ER_OK != status)
        {
            goto leave;
        }
        nbOfArgs++;
    }

    // send signal on AllJoyn
    signalFound = alljoyn_interfacedescription_getsignal(m_parent->GetInterfaceDescription(), m_exposedName.c_str(), &signalDescription);
    if (QCC_TRUE == signalFound)
    {
        alljoyn_busobject_signal(m_parent->GetBusObject(), NULL, ALLJOYN_SESSION_ID_ALL_HOSTED, signalDescription, args, nbOfArgs, 0, 0, NULL);
    }

leave:
    if (NULL != args)
    {
        alljoyn_msgarg_destroy(args);
    }
}

QStatus DeviceSignal::SetName(Platform::String ^name)
{
    QStatus status = ER_OK;

    m_exposedName.clear();

    if (name->IsEmpty())
    {
        status = ER_INVALID_DATA;
        goto leave;
    }

    AllJoynHelper::EncodePropertyOrMethodOrSignalName(name, m_exposedName);
    if (!m_parent->IsSignalNameUnique(m_exposedName))
    {
        // append unique id
        std::ostringstream tempString;
        m_exposedName += '_';
        tempString << m_parent->GetIndexForSignal();
        m_exposedName += tempString.str();
    }

leave:
    return status;
}

QStatus DeviceSignal::BuildSignature()
{
    QStatus status = ER_OK;

    m_signature.clear();
    m_parameterNames.clear();

    for (auto signalParam : m_adapterSignal->Params)
    {
        std::string tempSignature;
        std::string hint;
        if (nullptr == signalParam->Data)
        {
            // can't do anything with this param
            status = ER_BUS_BAD_SIGNATURE;
            goto leave;
        }

        //check if the value is of type IPropertyValue^
        auto propertyValue = dynamic_cast<IPropertyValue^>(signalParam->Data);
        if (nullptr == propertyValue)
        {
            if (TypeCode::Object == Type::GetTypeCode(signalParam->Data->GetType()))
            {
                IAdapterProperty ^tempProperty = dynamic_cast<IAdapterProperty ^> (signalParam->Data);
                if (nullptr == tempProperty)
                {
                    // wrong object type
                    status = ER_BUS_BAD_SIGNATURE;
                    goto leave;
                }

                // adapter object are exposed as string on AllJoyn
                tempSignature += "s";
                hint = " (bus object path)";
            }
            else
            {
                status = ER_BUS_BAD_SIGNATURE;
                goto leave;
            }
        }
        else
        {
            status = AllJoynHelper::GetSignature(propertyValue->Type, tempSignature);
            if (ER_OK != status)
            {
                goto leave;
            }
            m_signature += tempSignature;
        }

        // add parameter name to parameter list
        if (0 != m_parameterNames.length())
        {
            m_parameterNames == ",";
        }
        m_parameterNames += ConvertTo<std::string>(signalParam->Name->Data());
        m_parameterNames += hint;
    }

leave:
    return status;
}
<commit_msg>Update DeviceSignal.cpp (#383)<commit_after>//
// Copyright (c) 2015, Microsoft Corporation
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//

#include "pch.h"

#include <sstream>
#include "BridgeUtils.h"
#include "DeviceMain.h"
#include "DeviceSignal.h"
#include "AllJoynHelper.h"

using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation::Collections;
using namespace Windows::Foundation;

using namespace BridgeRT;
using namespace std;

DeviceSignal::DeviceSignal()
    : m_adapterSignal(nullptr)
{
}

DeviceSignal::~DeviceSignal()
{
}

QStatus DeviceSignal::Initialize(_In_ DeviceMain *parent, _In_ IAdapterSignal ^adapterSignal)
{
    QStatus status = ER_OK;

    // sanity check
    if (nullptr == parent)
    {
        status = ER_BAD_ARG_1;
        goto leave;
    }
    if (nullptr == adapterSignal)
    {
        status = ER_BAD_ARG_2;
        goto leave;
    }

    m_parent = parent;
    m_adapterSignal = adapterSignal;

    // build signal name
    status = SetName(m_adapterSignal->Name);
    if (ER_OK != status)
    {
        goto leave;
    }

    // build signatures and parameter list
    status = BuildSignature();
    if (ER_OK != status)
    {
        goto leave;
    }

    // add signal to interface
    status = alljoyn_interfacedescription_addsignal(m_parent->GetInterfaceDescription(),
        m_exposedName.c_str(),
        m_signature.c_str(),
        m_parameterNames.c_str(),
        0,
        nullptr);
    if (ER_OK != status)
    {
        goto leave;
    }

leave:
    return status;
}

void DeviceSignal::SendSignal()
{
    QStatus status = ER_OK;
    size_t nbOfArgs = 0;
    alljoyn_msgarg args = NULL;
    alljoyn_interfacedescription_member signalDescription;
    QCC_BOOL signalFound = QCC_FALSE;

    // create out arguments if necessary
    if (m_adapterSignal->Params->Size != 0)
    {
        args = alljoyn_msgarg_array_create(m_adapterSignal->Params->Size);
        if (NULL == args)
        {
            goto leave;
        }
    }

    // set arguments
    for (auto signalParam : m_adapterSignal->Params)
    {
        //check if the param is of type IPropertyValue
        auto propertyValue = dynamic_cast<IPropertyValue^>(signalParam->Data);
        if (nullptr == propertyValue)
        {
            //Not a property value, see if its an Object
            if (TypeCode::Object == Type::GetTypeCode(signalParam->Data->GetType()))
            {
                status = AllJoynHelper::SetMsgArgFromAdapterObject(signalParam, alljoyn_msgarg_array_element(args, nbOfArgs), m_parent);
            }
            else
            {
                goto leave;
            }
        }
        else
        {
            status = AllJoynHelper::SetMsgArg(signalParam, alljoyn_msgarg_array_element(args, nbOfArgs));
        }

        if (ER_OK != status)
        {
            goto leave;
        }
        nbOfArgs++;
    }

    // send signal on AllJoyn
    signalFound = alljoyn_interfacedescription_getsignal(m_parent->GetInterfaceDescription(), m_exposedName.c_str(), &signalDescription);
    if (QCC_TRUE == signalFound)
    {
        alljoyn_busobject_signal(m_parent->GetBusObject(), NULL, ALLJOYN_SESSION_ID_ALL_HOSTED, signalDescription, args, nbOfArgs, 0, 0, NULL);
    }

leave:
    if (NULL != args)
    {
        alljoyn_msgarg_destroy(args);
    }
}

QStatus DeviceSignal::SetName(Platform::String ^name)
{
    QStatus status = ER_OK;

    m_exposedName.clear();

    if (name->IsEmpty())
    {
        status = ER_INVALID_DATA;
        goto leave;
    }

    AllJoynHelper::EncodePropertyOrMethodOrSignalName(name, m_exposedName);
    if (!m_parent->IsSignalNameUnique(m_exposedName))
    {
        // append unique id
        std::ostringstream tempString;
        m_exposedName += '_';
        tempString << m_parent->GetIndexForSignal();
        m_exposedName += tempString.str();
    }

leave:
    return status;
}

QStatus DeviceSignal::BuildSignature()
{
    QStatus status = ER_OK;

    m_signature.clear();
    m_parameterNames.clear();

    for (auto signalParam : m_adapterSignal->Params)
    {
        std::string tempSignature;
        std::string hint;
        if (nullptr == signalParam->Data)
        {
            // can't do anything with this param
            status = ER_BUS_BAD_SIGNATURE;
            goto leave;
        }

        //check if the value is of type IPropertyValue^
        auto propertyValue = dynamic_cast<IPropertyValue^>(signalParam->Data);
        if (nullptr == propertyValue)
        {
            if (TypeCode::Object == Type::GetTypeCode(signalParam->Data->GetType()))
            {
                IAdapterProperty ^tempProperty = dynamic_cast<IAdapterProperty ^> (signalParam->Data);
                if (nullptr == tempProperty)
                {
                    // wrong object type
                    status = ER_BUS_BAD_SIGNATURE;
                    goto leave;
                }

                // adapter object are exposed as string on AllJoyn
                tempSignature += "s";
                hint = " (bus object path)";
            }
            else
            {
                status = ER_BUS_BAD_SIGNATURE;
                goto leave;
            }
        }
        else
        {
            status = AllJoynHelper::GetSignature(propertyValue->Type, tempSignature);
            if (ER_OK != status)
            {
                goto leave;
            }
            m_signature += tempSignature;
        }

        // add parameter name to parameter list
        if (0 != m_parameterNames.length())
        {
            m_parameterNames += ",";
        }
        m_parameterNames += ConvertTo<std::string>(signalParam->Name->Data());
        m_parameterNames += hint;
    }

leave:
    return status;
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libdui.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it 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.
**
****************************************************************************/

#include <QTest>
#include <QSignalSpy>
#include <QList>
#include <QObject>
#include <QGraphicsSceneMouseEvent>
#include <QModelIndex>
#include <DuiApplication>
#include <QStandardItemModel>
#include <QVariant>
#include <QGraphicsGridLayout>
#include <DuiImageWidget>
#include <DuiLabel>
#include <DuiWindow>
#include <DuiScene>
#include <DuiSceneManager>
#include <DuiPopupList>

#include "ut_duicombobox.h"
#include "duicancelevent.h"
#include "duicomboboxview.h"
#include "duicomboboxview_p.h"

DuiApplication *app;
DuiWindow *win;

void Ut_DuiComboBox::initTestCase()
{
    static int argc = 1;
    static char *argv[1] = { (char *) "./Ut_DuiComboBox" };
    app = new DuiApplication(argc, argv);

    win = new DuiWindow();
    win->setSceneManager(new DuiSceneManager());
}

void Ut_DuiComboBox::cleanupTestCase()
{
    delete win;
    win = NULL;
    delete app;
    app = NULL;
}

void Ut_DuiComboBox::init()
{
    m_combobox = new DuiComboBox();
}

void Ut_DuiComboBox::cleanup()
{
    if (m_combobox)
        delete m_combobox;
    m_combobox = NULL;
}

void Ut_DuiComboBox::testItemModel()
{
    QStringList buffer;
    int total = 10;
    for (int i = 0; i < total; i++)
        buffer << "Item" + QString::number(i);

    // test StandardItemModel
    m_combobox->addItems(buffer);

    QAbstractItemModel *itemModel = m_combobox->itemModel();
    QStandardItemModel *smodel = qobject_cast<QStandardItemModel *>(itemModel);
    QVERIFY(smodel != NULL);

    // test use model from outside
    QStringListModel model;
    model.setStringList(buffer);

    m_combobox->setItemModel(&model);
    QCOMPARE(&model, m_combobox->itemModel());
    QCOMPARE(m_combobox->count(), total);
}

void Ut_DuiComboBox::testActions()
{
    QStringList buffer;
    int total = 10;
    for (int i = 0; i < total; i++)
        buffer << "Item" + QString::number(i);

    // test add items
    m_combobox->addItems(buffer);
    QCOMPARE(m_combobox->count(), 10);

    QAbstractItemModel *itemModel = m_combobox->itemModel();
    QCOMPARE(itemModel->rowCount(), total);

    m_combobox->clear();
    QCOMPARE(m_combobox->count(), 0);

    m_combobox->addItem("Just a test");
    QCOMPARE(m_combobox->count(), 1);

    m_combobox->addItem("Icon", "Just a test");
    QCOMPARE(m_combobox->count(), 2);

    // test remove item
    m_combobox->removeItem(0);
    QCOMPARE(m_combobox->count(), 1);

    m_combobox->removeItem(0);
    QCOMPARE(m_combobox->count(), 0);

    // test insert item
    m_combobox->insertItem(0, "Just a test");
    QCOMPARE(m_combobox->count(), 1);

    m_combobox->insertItem(0, "Icon", "Just a test");
    QCOMPARE(m_combobox->count(), 2);

    m_combobox->clear();
    m_combobox->insertItems(0, buffer);
    QCOMPARE(m_combobox->count(), total);
}

void Ut_DuiComboBox::testCurrentIndex()
{
    QStringList buffer;
    int total = 10;
    for (int i = 0; i < total; i++)
        buffer << "Item" + QString::number(i);

    m_combobox->addItems(buffer);

    QSignalSpy spy1(m_combobox, SIGNAL(currentIndexChanged(int)));
    QSignalSpy spy2(m_combobox, SIGNAL(currentIndexChanged(QString)));

    m_combobox->setCurrentIndex(0);
    QCOMPARE(m_combobox->currentIndex(), 0);
    QCOMPARE(m_combobox->currentText(), QString("Item0"));

    QCOMPARE(spy1.count(), 1);
    QCOMPARE(spy2.count(), 1);

    QList<QVariant> arguments1 = spy1.takeFirst();
    QVERIFY(arguments1.at(0).type() == QVariant::Int);
    QVERIFY(arguments1.at(0).toInt() == 0);

    QList<QVariant> arguments2 = spy2.takeFirst();
    QVERIFY(arguments2.at(0).type() == QVariant::String);
    QCOMPARE(arguments2.at(0).toString(), QString("Item0"));
}

void Ut_DuiComboBox::testFunctions()
{
    QString value = "test";
    m_combobox->setIconID(value);
    QCOMPARE(m_combobox->iconID(), value);

    m_combobox->setTitle(value);
    QCOMPARE(m_combobox->title(), value);

    m_combobox->setIconVisible(false);
    QCOMPARE(m_combobox->isIconVisible(), false);

    m_combobox->setIconVisible(true);
    QCOMPARE(m_combobox->isIconVisible(), true);

    m_combobox->insertItem(0, "Just a test");
    m_combobox->setItemText(0, value);
    QCOMPARE(m_combobox->itemText(0), value);

    m_combobox->setItemIconID(0, value);
    QCOMPARE(m_combobox->itemIconID(0), value);
}

void Ut_DuiComboBox::testCancelEvent()
{
    QSignalSpy showPopupSpy(m_combobox, SIGNAL(showPopupList()));

    QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
    m_combobox->mousePressEvent(&mouseEvent);
    QVERIFY(m_combobox->isDown() == true);

    DuiCancelEvent event;
    m_combobox->cancelEvent(&event);

    QCOMPARE(showPopupSpy.count(), 0);
    QVERIFY(m_combobox->isDown() == false);
}

void Ut_DuiComboBox::testIconVisibility()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    m_combobox->setTitle("Title");
    view->updateData(QList<const char *>() << DuiComboBoxModel::Title);
    QCOMPARE(viewPrivate->icon->isVisible(), false);
    QCOMPARE(viewPrivate->layout->itemAt(0, 0), viewPrivate->title);

    m_combobox->setIconID("Icon-music");
    view->updateData(QList<const char *>() << DuiComboBoxModel::IconID);
    QCOMPARE(viewPrivate->icon->isVisible(), true);
    QCOMPARE(viewPrivate->layout->itemAt(0, 0), viewPrivate->icon);

    m_combobox->setIconVisible(false);
    view->updateData(QList<const char *>() << DuiComboBoxModel::IconVisible);
    QCOMPARE(viewPrivate->icon->isVisible(), false);
    QCOMPARE(viewPrivate->layout->itemAt(0, 0), viewPrivate->title);

    m_combobox->setIconVisible(true);
    view->updateData(QList<const char *>() << DuiComboBoxModel::IconVisible);
    QCOMPARE(viewPrivate->icon->isVisible(), true);
    QCOMPARE(viewPrivate->layout->itemAt(0, 0), viewPrivate->icon);
}

void Ut_DuiComboBox::testClickSlot()
{
    win->scene()->addItem(m_combobox);

    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    m_combobox->addItem("Item1");
    m_combobox->addItem("Item2");

    m_combobox->click();

    QVERIFY(viewPrivate->popuplist != 0);
    QVERIFY(viewPrivate->popuplist->isVisible());

    win->scene()->removeItem(m_combobox);
}

void Ut_DuiComboBox::testBuiltinModel()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    m_combobox->addItems(QStringList() << "item0" << "item1" << "item2" << "item3");

    // select item2
    m_combobox->setCurrentIndex(2);
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item2"));
    // remove item1, index should change
    m_combobox->removeItem(1);
    QCOMPARE(m_combobox->currentIndex(), 1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item2"));
    // remove current item
    m_combobox->removeItem(1);
    QCOMPARE(m_combobox->currentIndex(), -1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("!! Tap to Select"));
    // check that after removing items everything looks ok
    QCOMPARE(m_combobox->count(), 2);
    m_combobox->setCurrentIndex(1);
    QCOMPARE(m_combobox->currentIndex(), 1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item3"));
    // add one item
    m_combobox->insertItem(0, QString("itemX"));
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item3"));

    // change current item text
    m_combobox->setItemText(2, QString("beef"));
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("beef"));
}

void Ut_DuiComboBox::testModelSwitching()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    m_combobox->addItems(QStringList() << "item0" << "item1" << "item2" << "item3");

    m_combobox->setCurrentIndex(2);
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item2"));

    QStringListModel *strListModel = new QStringListModel();
    strListModel->setStringList(QStringList() << "foo0" << "foo1" << "foo2" << "foo3");
    m_combobox->setItemModel(strListModel);

    // model changed selection should reset
    QCOMPARE(m_combobox->currentIndex(), -1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("!! Tap to Select"));
}

void Ut_DuiComboBox::testStringListModel()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    QStringListModel *strListModel = new QStringListModel();
    strListModel->setStringList(QStringList() << "foo0" << "foo1" << "foo2" << "foo3");
    m_combobox->setItemModel(strListModel);

    // select item 2
    m_combobox->setCurrentIndex(2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("foo2"));
    // remove item1, index should change
    strListModel->removeRow(1);
    QCOMPARE(m_combobox->currentIndex(), 1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("foo2"));
    // remove current item
    strListModel->removeRow(1);
    QCOMPARE(m_combobox->currentIndex(), -1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("!! Tap to Select"));
    // check that after removing items everything looks ok
    QCOMPARE(m_combobox->count(), 2);
    m_combobox->setCurrentIndex(1);
    QCOMPARE(m_combobox->currentIndex(), 1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("foo3"));
    // add one item
    strListModel->insertRow(0);
    strListModel->setData(strListModel->index(0, 0), QString("fooX"), Qt::DisplayRole);
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("foo3"));

    // change current item text
    strListModel->setData(strListModel->index(2, 0), QString("lamb"), Qt::DisplayRole);
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("lamb"));
}

void Ut_DuiComboBox::testStringListModelSetStringList()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    QStringListModel *strListModel = new QStringListModel();
    strListModel->setStringList(QStringList() << "foo0" << "foo1" << "foo2" << "foo3");
    m_combobox->setItemModel(strListModel);

    // select foo2
    m_combobox->setCurrentIndex(2);
    // change string list completely
    strListModel->setStringList(QStringList() << "bar0" << "bar1" << "bar2" << "bar3");
    QCOMPARE(m_combobox->currentIndex(), -1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("!! Tap to Select"));
}

QTEST_APPLESS_MAIN(Ut_DuiComboBox)

<commit_msg>Changes:  Unit tests ut_duicombobox - fixed right localization string and application name RevBy: TrustMe Details:<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libdui.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it 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.
**
****************************************************************************/

#include <QTest>
#include <QSignalSpy>
#include <QList>
#include <QObject>
#include <QGraphicsSceneMouseEvent>
#include <QModelIndex>
#include <DuiApplication>
#include <QStandardItemModel>
#include <QVariant>
#include <QGraphicsGridLayout>
#include <DuiImageWidget>
#include <DuiLabel>
#include <DuiWindow>
#include <DuiScene>
#include <DuiSceneManager>
#include <DuiPopupList>

#include "ut_duicombobox.h"
#include "duicancelevent.h"
#include "duicomboboxview.h"
#include "duicomboboxview_p.h"

DuiApplication *app;
DuiWindow *win;

void Ut_DuiComboBox::initTestCase()
{
    static int argc = 1;
    static char *argv[1] = { (char *) "./ut_duicombobox" };
    app = new DuiApplication(argc, argv);

    win = new DuiWindow();
    win->setSceneManager(new DuiSceneManager());
}

void Ut_DuiComboBox::cleanupTestCase()
{
    delete win;
    win = NULL;
    delete app;
    app = NULL;
}

void Ut_DuiComboBox::init()
{
    m_combobox = new DuiComboBox();
}

void Ut_DuiComboBox::cleanup()
{
    if (m_combobox)
        delete m_combobox;
    m_combobox = NULL;
}

void Ut_DuiComboBox::testItemModel()
{
    QStringList buffer;
    int total = 10;
    for (int i = 0; i < total; i++)
        buffer << "Item" + QString::number(i);

    // test StandardItemModel
    m_combobox->addItems(buffer);

    QAbstractItemModel *itemModel = m_combobox->itemModel();
    QStandardItemModel *smodel = qobject_cast<QStandardItemModel *>(itemModel);
    QVERIFY(smodel != NULL);

    // test use model from outside
    QStringListModel model;
    model.setStringList(buffer);

    m_combobox->setItemModel(&model);
    QCOMPARE(&model, m_combobox->itemModel());
    QCOMPARE(m_combobox->count(), total);
}

void Ut_DuiComboBox::testActions()
{
    QStringList buffer;
    int total = 10;
    for (int i = 0; i < total; i++)
        buffer << "Item" + QString::number(i);

    // test add items
    m_combobox->addItems(buffer);
    QCOMPARE(m_combobox->count(), 10);

    QAbstractItemModel *itemModel = m_combobox->itemModel();
    QCOMPARE(itemModel->rowCount(), total);

    m_combobox->clear();
    QCOMPARE(m_combobox->count(), 0);

    m_combobox->addItem("Just a test");
    QCOMPARE(m_combobox->count(), 1);

    m_combobox->addItem("Icon", "Just a test");
    QCOMPARE(m_combobox->count(), 2);

    // test remove item
    m_combobox->removeItem(0);
    QCOMPARE(m_combobox->count(), 1);

    m_combobox->removeItem(0);
    QCOMPARE(m_combobox->count(), 0);

    // test insert item
    m_combobox->insertItem(0, "Just a test");
    QCOMPARE(m_combobox->count(), 1);

    m_combobox->insertItem(0, "Icon", "Just a test");
    QCOMPARE(m_combobox->count(), 2);

    m_combobox->clear();
    m_combobox->insertItems(0, buffer);
    QCOMPARE(m_combobox->count(), total);
}

void Ut_DuiComboBox::testCurrentIndex()
{
    QStringList buffer;
    int total = 10;
    for (int i = 0; i < total; i++)
        buffer << "Item" + QString::number(i);

    m_combobox->addItems(buffer);

    QSignalSpy spy1(m_combobox, SIGNAL(currentIndexChanged(int)));
    QSignalSpy spy2(m_combobox, SIGNAL(currentIndexChanged(QString)));

    m_combobox->setCurrentIndex(0);
    QCOMPARE(m_combobox->currentIndex(), 0);
    QCOMPARE(m_combobox->currentText(), QString("Item0"));

    QCOMPARE(spy1.count(), 1);
    QCOMPARE(spy2.count(), 1);

    QList<QVariant> arguments1 = spy1.takeFirst();
    QVERIFY(arguments1.at(0).type() == QVariant::Int);
    QVERIFY(arguments1.at(0).toInt() == 0);

    QList<QVariant> arguments2 = spy2.takeFirst();
    QVERIFY(arguments2.at(0).type() == QVariant::String);
    QCOMPARE(arguments2.at(0).toString(), QString("Item0"));
}

void Ut_DuiComboBox::testFunctions()
{
    QString value = "test";
    m_combobox->setIconID(value);
    QCOMPARE(m_combobox->iconID(), value);

    m_combobox->setTitle(value);
    QCOMPARE(m_combobox->title(), value);

    m_combobox->setIconVisible(false);
    QCOMPARE(m_combobox->isIconVisible(), false);

    m_combobox->setIconVisible(true);
    QCOMPARE(m_combobox->isIconVisible(), true);

    m_combobox->insertItem(0, "Just a test");
    m_combobox->setItemText(0, value);
    QCOMPARE(m_combobox->itemText(0), value);

    m_combobox->setItemIconID(0, value);
    QCOMPARE(m_combobox->itemIconID(0), value);
}

void Ut_DuiComboBox::testCancelEvent()
{
    QSignalSpy showPopupSpy(m_combobox, SIGNAL(showPopupList()));

    QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
    m_combobox->mousePressEvent(&mouseEvent);
    QVERIFY(m_combobox->isDown() == true);

    DuiCancelEvent event;
    m_combobox->cancelEvent(&event);

    QCOMPARE(showPopupSpy.count(), 0);
    QVERIFY(m_combobox->isDown() == false);
}

void Ut_DuiComboBox::testIconVisibility()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    m_combobox->setTitle("Title");
    view->updateData(QList<const char *>() << DuiComboBoxModel::Title);
    QCOMPARE(viewPrivate->icon->isVisible(), false);
    QCOMPARE(viewPrivate->layout->itemAt(0, 0), viewPrivate->title);

    m_combobox->setIconID("Icon-music");
    view->updateData(QList<const char *>() << DuiComboBoxModel::IconID);
    QCOMPARE(viewPrivate->icon->isVisible(), true);
    QCOMPARE(viewPrivate->layout->itemAt(0, 0), viewPrivate->icon);

    m_combobox->setIconVisible(false);
    view->updateData(QList<const char *>() << DuiComboBoxModel::IconVisible);
    QCOMPARE(viewPrivate->icon->isVisible(), false);
    QCOMPARE(viewPrivate->layout->itemAt(0, 0), viewPrivate->title);

    m_combobox->setIconVisible(true);
    view->updateData(QList<const char *>() << DuiComboBoxModel::IconVisible);
    QCOMPARE(viewPrivate->icon->isVisible(), true);
    QCOMPARE(viewPrivate->layout->itemAt(0, 0), viewPrivate->icon);
}

void Ut_DuiComboBox::testClickSlot()
{
    win->scene()->addItem(m_combobox);

    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    m_combobox->addItem("Item1");
    m_combobox->addItem("Item2");

    m_combobox->click();

    QVERIFY(viewPrivate->popuplist != 0);
    QVERIFY(viewPrivate->popuplist->isVisible());

    win->scene()->removeItem(m_combobox);
}

void Ut_DuiComboBox::testBuiltinModel()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    m_combobox->addItems(QStringList() << "item0" << "item1" << "item2" << "item3");

    // select item2
    m_combobox->setCurrentIndex(2);
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item2"));
    // remove item1, index should change
    m_combobox->removeItem(1);
    QCOMPARE(m_combobox->currentIndex(), 1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item2"));
    // remove current item
    m_combobox->removeItem(1);
    QCOMPARE(m_combobox->currentIndex(), -1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("Tap to Select"));
    // check that after removing items everything looks ok
    QCOMPARE(m_combobox->count(), 2);
    m_combobox->setCurrentIndex(1);
    QCOMPARE(m_combobox->currentIndex(), 1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item3"));
    // add one item
    m_combobox->insertItem(0, QString("itemX"));
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item3"));

    // change current item text
    m_combobox->setItemText(2, QString("beef"));
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("beef"));
}

void Ut_DuiComboBox::testModelSwitching()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    m_combobox->addItems(QStringList() << "item0" << "item1" << "item2" << "item3");

    m_combobox->setCurrentIndex(2);
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("item2"));

    QStringListModel *strListModel = new QStringListModel();
    strListModel->setStringList(QStringList() << "foo0" << "foo1" << "foo2" << "foo3");
    m_combobox->setItemModel(strListModel);

    // model changed selection should reset
    QCOMPARE(m_combobox->currentIndex(), -1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("Tap to Select"));
}

void Ut_DuiComboBox::testStringListModel()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    QStringListModel *strListModel = new QStringListModel();
    strListModel->setStringList(QStringList() << "foo0" << "foo1" << "foo2" << "foo3");
    m_combobox->setItemModel(strListModel);

    // select item 2
    m_combobox->setCurrentIndex(2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("foo2"));
    // remove item1, index should change
    strListModel->removeRow(1);
    QCOMPARE(m_combobox->currentIndex(), 1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("foo2"));
    // remove current item
    strListModel->removeRow(1);
    QCOMPARE(m_combobox->currentIndex(), -1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("Tap to Select"));
    // check that after removing items everything looks ok
    QCOMPARE(m_combobox->count(), 2);
    m_combobox->setCurrentIndex(1);
    QCOMPARE(m_combobox->currentIndex(), 1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("foo3"));
    // add one item
    strListModel->insertRow(0);
    strListModel->setData(strListModel->index(0, 0), QString("fooX"), Qt::DisplayRole);
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("foo3"));

    // change current item text
    strListModel->setData(strListModel->index(2, 0), QString("lamb"), Qt::DisplayRole);
    QCOMPARE(m_combobox->currentIndex(), 2);
    QCOMPARE(viewPrivate->subtitle->text(), QString("lamb"));
}

void Ut_DuiComboBox::testStringListModelSetStringList()
{
    DuiComboBoxView *view = (DuiComboBoxView *)m_combobox->view();
    DuiComboBoxViewPrivate *viewPrivate = view->d_func();

    QStringListModel *strListModel = new QStringListModel();
    strListModel->setStringList(QStringList() << "foo0" << "foo1" << "foo2" << "foo3");
    m_combobox->setItemModel(strListModel);

    // select foo2
    m_combobox->setCurrentIndex(2);
    // change string list completely
    strListModel->setStringList(QStringList() << "bar0" << "bar1" << "bar2" << "bar3");
    QCOMPARE(m_combobox->currentIndex(), -1);
    QCOMPARE(viewPrivate->subtitle->text(), QString("Tap to Select"));
}

QTEST_APPLESS_MAIN(Ut_DuiComboBox)

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2014, Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "Message.h"
#include <assert.h>
#include "Socket.h"
#include "RemoteProcessorProtocol.h"
#include <string.h>
#include <assert.h>
#include <errno.h>

CMessage::CMessage(uint8_t ucMsgId) : _ucMsgId(ucMsgId), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
{
}

CMessage::CMessage() : _ucMsgId((uint8_t)-1), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
{
}

CMessage::~CMessage()
{
    delete [] _pucData;
}

// Msg Id
uint8_t CMessage::getMsgId() const
{
    return _ucMsgId;
}

// Data
void CMessage::writeData(const void* pvData, uint32_t uiSize)
{
    assert(_uiIndex + uiSize <= _uiDataSize);

    // Copy
    memcpy(&_pucData[_uiIndex], pvData, uiSize);

    // Index
    _uiIndex += uiSize;
}

void CMessage::readData(void* pvData, uint32_t uiSize)
{
    assert(_uiIndex + uiSize <= _uiDataSize);

    // Copy
    memcpy(pvData, &_pucData[_uiIndex], uiSize);

    // Index
    _uiIndex += uiSize;
}

void CMessage::writeString(const string& strData)
{
    // Size
    uint32_t uiSize = strData.length();

    writeData(&uiSize, sizeof(uiSize));

    // Content
    writeData(strData.c_str(), uiSize);
}

void CMessage::readString(string& strData)
{
    // Size
    uint32_t uiSize;

    readData(&uiSize, sizeof(uiSize));

    // Data
    char* pcData = new char[uiSize + 1];

    // Content
    readData(pcData, uiSize);

    // NULL-terminate string
    pcData[uiSize] = '\0';

    // Output
    strData = pcData;

    // Delete
    delete [] pcData;
}

uint32_t CMessage::getStringSize(const string& strData) const
{
    // Return string length plus room to store its length
    return strData.length() + sizeof(uint32_t);
}

// Remaining data size
uint32_t CMessage::getRemainingDataSize() const
{
    return _uiDataSize - _uiIndex;
}

// Send/Receive
CMessage::Result CMessage::serialize(CSocket* pSocket, bool bOut, string& strError)
{
    if (bOut) {

        // Make room for data to send
        allocateData(getDataSize());

        // Get data from derived
        fillDataToSend();

        // Finished providing data?
        assert(_uiIndex == _uiDataSize);

        // First send sync word
        uint16_t uiSyncWord = SYNC_WORD;

        if (!pSocket->write(&uiSyncWord, sizeof(uiSyncWord))) {

            if (pSocket->hasPeerDisconnected()) {
                return peerDisconnected;
            }
            return error;
        }

        // Size
        uint32_t uiSize = sizeof(_ucMsgId) + _uiDataSize;

        if (!pSocket->write(&uiSize, sizeof(uiSize))) {

            strError += string("Size write failed: ") + strerror(errno);
            return error;
        }

        // Msg Id
        if (!pSocket->write(&_ucMsgId, sizeof(_ucMsgId))) {

            strError += string("Msg write failed: ") + strerror(errno);
            return error;
        }

        // Data
        if (!pSocket->write(_pucData, _uiDataSize)) {

            strError = string("Data write failed: ") + strerror(errno);
            return error;
        }

        // Checksum
        uint8_t ucChecksum = computeChecksum();

        if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) {

            strError = string("Checksum write failed: ") + strerror(errno);
            return error;
        }

    } else {
        // First read sync word
        uint16_t uiSyncWord;

        if (!pSocket->read(&uiSyncWord, sizeof(uiSyncWord))) {

            strError = string("Sync read failed: ") + strerror(errno);
            if (pSocket->hasPeerDisconnected()) {
                return peerDisconnected;
            }
            return error;
        }

        // Check Sync word
        if (uiSyncWord != SYNC_WORD) {

            strError = "Sync word incorrect";
            return error;
        }

        // Size
        uint32_t uiSize;

        if (!pSocket->read(&uiSize, sizeof(uiSize))) {

            strError = string("Size read failed: ") + strerror(errno);
            return error;
        }

        // Msg Id
        if (!pSocket->read(&_ucMsgId, sizeof(_ucMsgId))) {

            strError = string("Msg id read failed: ") + strerror(errno);
            return error;
        }

        // Data

        // Allocate
        allocateData(uiSize - sizeof(_ucMsgId));

        // Data receive
        if (!pSocket->read(_pucData, _uiDataSize)) {

            strError = string("Data read failed: ") + strerror(errno);
            return error;
        }

        // Checksum
        uint8_t ucChecksum;

        if (!pSocket->read(&ucChecksum, sizeof(ucChecksum))) {

            strError = string("Checksum read failed: ") + strerror(errno);
            return error;
        }
        // Compare
        if (ucChecksum != computeChecksum()) {

            strError = "Received checksum != computed checksum";
            return error;
        }

        // Collect data in derived
        collectReceivedData();
    }

    return success;
}

// Checksum
uint8_t CMessage::computeChecksum() const
{
    uint8_t uiChecksum = _ucMsgId;

    uint32_t uiIndex;

    for (uiIndex = 0; uiIndex < _uiDataSize; uiIndex++) {

        uiChecksum += _pucData[uiIndex];
    }

    return uiChecksum;
}

// Data allocation
void CMessage::allocateData(uint32_t uiSize)
{
    // Remove previous one
    if (_pucData) {

        delete [] _pucData;
    }
    // Do allocate
    _pucData = new uint8_t[uiSize];

    // Record size
    _uiDataSize = uiSize;

    // Reset Index
    _uiIndex = 0;
}
<commit_msg>Remove non ASCII char from log string<commit_after>/*
 * Copyright (c) 2011-2014, Intel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "Message.h"
#include <assert.h>
#include "Socket.h"
#include "RemoteProcessorProtocol.h"
#include <string.h>
#include <assert.h>
#include <errno.h>

CMessage::CMessage(uint8_t ucMsgId) : _ucMsgId(ucMsgId), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
{
}

CMessage::CMessage() : _ucMsgId((uint8_t)-1), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
{
}

CMessage::~CMessage()
{
    delete [] _pucData;
}

// Msg Id
uint8_t CMessage::getMsgId() const
{
    return _ucMsgId;
}

// Data
void CMessage::writeData(const void* pvData, uint32_t uiSize)
{
    assert(_uiIndex + uiSize <= _uiDataSize);

    // Copy
    memcpy(&_pucData[_uiIndex], pvData, uiSize);

    // Index
    _uiIndex += uiSize;
}

void CMessage::readData(void* pvData, uint32_t uiSize)
{
    assert(_uiIndex + uiSize <= _uiDataSize);

    // Copy
    memcpy(pvData, &_pucData[_uiIndex], uiSize);

    // Index
    _uiIndex += uiSize;
}

void CMessage::writeString(const string& strData)
{
    // Size
    uint32_t uiSize = strData.length();

    writeData(&uiSize, sizeof(uiSize));

    // Content
    writeData(strData.c_str(), uiSize);
}

void CMessage::readString(string& strData)
{
    // Size
    uint32_t uiSize;

    readData(&uiSize, sizeof(uiSize));

    // Data
    char* pcData = new char[uiSize + 1];

    // Content
    readData(pcData, uiSize);

    // NULL-terminate string
    pcData[uiSize] = '\0';

    // Output
    strData = pcData;

    // Delete
    delete [] pcData;
}

uint32_t CMessage::getStringSize(const string& strData) const
{
    // Return string length plus room to store its length
    return strData.length() + sizeof(uint32_t);
}

// Remaining data size
uint32_t CMessage::getRemainingDataSize() const
{
    return _uiDataSize - _uiIndex;
}

// Send/Receive
CMessage::Result CMessage::serialize(CSocket* pSocket, bool bOut, string& strError)
{
    if (bOut) {

        // Make room for data to send
        allocateData(getDataSize());

        // Get data from derived
        fillDataToSend();

        // Finished providing data?
        assert(_uiIndex == _uiDataSize);

        // First send sync word
        uint16_t uiSyncWord = SYNC_WORD;

        if (!pSocket->write(&uiSyncWord, sizeof(uiSyncWord))) {

            if (pSocket->hasPeerDisconnected()) {
                return peerDisconnected;
            }
            return error;
        }

        // Size
        uint32_t uiSize = sizeof(_ucMsgId) + _uiDataSize;

        if (!pSocket->write(&uiSize, sizeof(uiSize))) {

            strError += string("Size write failed: ") + strerror(errno);
            return error;
        }

        // Msg Id
        if (!pSocket->write(&_ucMsgId, sizeof(_ucMsgId))) {

            strError += string("Msg write failed: ") + strerror(errno);
            return error;
        }

        // Data
        if (!pSocket->write(_pucData, _uiDataSize)) {

            strError = string("Data write failed: ") + strerror(errno);
            return error;
        }

        // Checksum
        uint8_t ucChecksum = computeChecksum();

        if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) {

            strError = string("Checksum write failed: ") + strerror(errno);
            return error;
        }

    } else {
        // First read sync word
        uint16_t uiSyncWord;

        if (!pSocket->read(&uiSyncWord, sizeof(uiSyncWord))) {

            strError = string("Sync read failed: ") + strerror(errno);
            if (pSocket->hasPeerDisconnected()) {
                return peerDisconnected;
            }
            return error;
        }

        // Check Sync word
        if (uiSyncWord != SYNC_WORD) {

            strError = "Sync word incorrect";
            return error;
        }

        // Size
        uint32_t uiSize;

        if (!pSocket->read(&uiSize, sizeof(uiSize))) {

            strError = string("Size read failed: ") + strerror(errno);
            return error;
        }

        // Msg Id
        if (!pSocket->read(&_ucMsgId, sizeof(_ucMsgId))) {

            strError = string("Msg id read failed: ") + strerror(errno);
            return error;
        }

        // Data

        // Allocate
        allocateData(uiSize - sizeof(_ucMsgId));

        // Data receive
        if (!pSocket->read(_pucData, _uiDataSize)) {

            strError = string("Data read failed: ") + strerror(errno);
            return error;
        }

        // Checksum
        uint8_t ucChecksum;

        if (!pSocket->read(&ucChecksum, sizeof(ucChecksum))) {

            strError = string("Checksum read failed: ") + strerror(errno);
            return error;
        }
        // Compare
        if (ucChecksum != computeChecksum()) {

            strError = "Received checksum != computed checksum";
            return error;
        }

        // Collect data in derived
        collectReceivedData();
    }

    return success;
}

// Checksum
uint8_t CMessage::computeChecksum() const
{
    uint8_t uiChecksum = _ucMsgId;

    uint32_t uiIndex;

    for (uiIndex = 0; uiIndex < _uiDataSize; uiIndex++) {

        uiChecksum += _pucData[uiIndex];
    }

    return uiChecksum;
}

// Data allocation
void CMessage::allocateData(uint32_t uiSize)
{
    // Remove previous one
    if (_pucData) {

        delete [] _pucData;
    }
    // Do allocate
    _pucData = new uint8_t[uiSize];

    // Record size
    _uiDataSize = uiSize;

    // Reset Index
    _uiIndex = 0;
}
<|endoftext|>


<commit_before><commit_msg>Fix an accidental nested extern and conversion cleanup from brett's landing.<commit_after><|endoftext|>


<commit_before>/*
 *  despot1hifi.cpp
 *
 *  Created by Tobias Wood on 17/10/2011.
 *  Copyright (c) 2011-2013 Tobias Wood.
 *
 *  Based on code by Sean Deoni
 *
 *  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/.
 *
 */

#include <getopt.h>
#include <iostream>
#include <Eigen/Dense>
#include <unsupported/Eigen/LevenbergMarquardt>
#include <unsupported/Eigen/NumericalDiff>

#include "itkImageFileReader.h"

#include "QI/Sequences/Sequences.h"
#include "QI/Util.h"
#include "QI/IO.h"
#include "Filters/ApplyAlgorithmFilter.h"

using namespace std;
using namespace Eigen;

//******************************************************************************
// Arguments / Usage
//******************************************************************************
const string usage {
"Usage is: qidespot1hifi [options] spgr_input ir-spgr_input\n\
\
Options:\n\
    --help, -h        : Print this message\n\
    --verbose, -v     : Print more information\n\
    --no-prompt, -n   : Suppress input prompts\n\
    --mprage, -M      : Use a generic MP-RAGE sequence, not GE IR-SPGR\n\
    --out, -o path    : Add a prefix to the output filenames\n\
    --mask, -m file   : Mask input with specified file\n\
    --thresh, -t n    : Threshold maps at PD < n\n\
    --clamp, -c n     : Clamp T1 between 0 and n\n\
    --its, -i N       : Max iterations for NLLS (default 4)\n\
    --resids, -r      : Write out per flip-angle residuals\n\
    --threads, -T N   : Use N threads (default=4, 0=hardware limit)\n"
};

static bool verbose = false, prompt = true, IR = true, all_residuals = false;
static size_t nIterations = 4, num_threads = 4;
static string outPrefix;
static double thresh = -numeric_limits<double>::infinity();
static double clamp_lo = -numeric_limits<double>::infinity(), clamp_hi = numeric_limits<double>::infinity();
static const struct option long_opts[] = {
    {"help", no_argument, 0, 'h'},
    {"verbose", no_argument, 0, 'v'},
    {"no-prompt", no_argument, 0, 'n'},
    {"mprage", no_argument, 0, 'M'},
    {"mask", required_argument, 0, 'm'},
    {"out", required_argument, 0, 'o'},
    {"thresh", required_argument, 0, 't'},
    {"clamp", required_argument, 0, 'c'},
    {"its", required_argument, 0, 'i'},
    {"resids", no_argument, 0, 'r'},
    {"threads", required_argument, 0, 'T'},
    {0, 0, 0, 0}
};
static const char *short_opts = "hvnMm:o:t:c:s:p:i:rT:";

// HIFI Algorithm - includes optimising B1
class HIFIFunctor : public DenseFunctor<double> {
    protected:
        const shared_ptr<QI::SPGRSimple> m_spgr;
        const shared_ptr<QI::MPRAGE> m_mprage;
        const ArrayXd m_data;

    public:
        HIFIFunctor(const shared_ptr<QI::SPGRSimple> spgr,
                    const shared_ptr<QI::MPRAGE> mprage,
                    const ArrayXd &data) :
            DenseFunctor<double>(3, spgr->size() + mprage->size()),
            m_spgr(spgr), m_mprage(mprage), m_data(data)
        {
            assert(static_cast<size_t>(m_data.rows()) == values());
        }

        int operator()(const Ref<VectorXd> &params, Ref<ArrayXd> diffs) const {
            eigen_assert(diffs.size() == values());

            ArrayXd s(values());
            s.head(m_spgr->size()) = QI::One_SPGR_Magnitude(m_spgr->flip(), m_spgr->TR(), params[0], params[1], params[2]);
            s.tail(m_mprage->size()) = QI::One_MPRAGE(m_mprage->flip()[0], m_mprage->TR(), m_mprage->m_Nseg, m_mprage->m_Nk0, m_mprage->m_TI, m_mprage->m_TD,
                                                      params[0], params[1], params[2], m_mprage->m_eta).cwiseAbs();
            diffs = s - m_data;
            return 0;
        }
};

class HIFIAlgo : public QI::ApplyF::Algorithm {
private:
    shared_ptr<QI::SPGRSimple> m_spgr;
    shared_ptr<QI::MPRAGE> m_mprage;
    size_t m_iterations = 15; // From tests this seems to be a sensible maximum number
    double m_thresh = -numeric_limits<double>::infinity();
    double m_lo = -numeric_limits<double>::infinity();
    double m_hi = numeric_limits<double>::infinity();
public:
    void setSequences(const shared_ptr<QI::SPGRSimple> &s, const shared_ptr<QI::MPRAGE> &m) { m_spgr = s; m_mprage = m;}
    void setIterations(size_t n) { m_iterations = n; }
    void setThreshold(double t) { m_thresh = t; }
    void setClamp(double lo, double hi) { m_lo = lo; m_hi = hi; }
    size_t numInputs() const override  { return 2; }
    size_t numConsts() const override  { return 0; }
    size_t numOutputs() const override { return 3; }
    size_t dataSize() const override   { return m_spgr->size() + m_mprage->size(); }
    const float &zero(const size_t i) const override { static float zero = 0; return zero; }

    virtual std::vector<float> defaultConsts() const override {
        // No constants for HIFI
        std::vector<float> def(0);
        return def;
    }

    virtual bool apply(const std::vector<TInput> &inputs, const std::vector<TConst> &, // No constants, remove name to silence compiler warnings
                       std::vector<TOutput> &outputs, TConst &residual,
                       TInput &resids, TIters &its) const override
    {
        Eigen::Map<const ArrayXf> spgr(inputs[0].GetDataPointer(), inputs[0].Size());
        Eigen::Map<const ArrayXf> irspgr(inputs[1].GetDataPointer(), inputs[1].Size());
        ArrayXf indata(dataSize()); indata << spgr, irspgr;
        const ArrayXd data = indata.cast<double>() / indata.abs().maxCoeff(); // Scale to make parameters roughly equal
        HIFIFunctor f(m_spgr, m_mprage, data);
        NumericalDiff<HIFIFunctor> nDiff(f);
        LevenbergMarquardt<NumericalDiff<HIFIFunctor>> lm(nDiff);
        // LevenbergMarquardt does not currently have a good interface, have to do things in steps
        lm.setMaxfev(m_iterations * (data.rows() + 1));
        VectorXd p(3); p << 10., 1., 1.; // Initial guess
        lm.minimize(p);
        ArrayXd r(indata.rows());
        f(p, r); // Get the residuals

        if (p[0] < m_thresh)
            p[0] = 0;
        else
            outputs[0] = p[0] * indata.abs().maxCoeff();
        outputs[1] = QI::clamp(p[1], m_lo, m_hi);
        outputs[2] = p[2];
        residual = sqrt(r.square().sum() / r.rows());
        ArrayXf rf = r.cast<float>();
        resids = itk::VariableLengthVector<float>(rf.data(), rf.rows());
        its = lm.iterations();
        return true;
    }
};

//******************************************************************************
// Main
//******************************************************************************
int main(int argc, char **argv) {
    Eigen::initParallel();
    QI::VolumeF::Pointer mask = ITK_NULLPTR;
    auto hifi = make_shared<HIFIAlgo>();
    int indexptr = 0, c;
    while ((c = getopt_long(argc, argv, short_opts, long_opts, &indexptr)) != -1) {
        switch (c) {
            case 'v': verbose = true; break;
            case 'n': prompt = false; break;
            case 'M': IR = false; break;
            case 'm':
                if (verbose) cout << "Opening mask file: " << optarg << endl;
                mask = QI::ReadImage(optarg);
                break;
            case 'o':
                outPrefix = optarg;
                if (verbose) cout << "Output prefix will be: " << outPrefix << endl;
                break;
            case 't': hifi->setThreshold(atof(optarg)); break;
            case 'c': hifi->setClamp(0, atof(optarg)); break;
            case 'i': hifi->setIterations(atoi(optarg)); break;
            case 'r': all_residuals = true; break;
            case 'T':
                num_threads = stoi(optarg);
                if (num_threads == 0)
                    num_threads = std::thread::hardware_concurrency();
                break;
            case 'h':
                cout << QI::GetVersion() << endl << usage << endl;
                return EXIT_SUCCESS;
            case '?': // getopt will print an error message
                return EXIT_FAILURE;
            default:
                cout << "Unhandled option " << string(1, c) << endl;
                return EXIT_FAILURE;
        }
    }
    if ((argc - optind) != 2) {
        cerr << "Incorrect number of arguments." << endl;
        cout << QI::GetVersion() << endl << usage << endl;
        return EXIT_FAILURE;
    }

    if (verbose) cout << "Opening SPGR file: " << argv[optind] << endl;
    auto spgrImg = QI::ReadVectorImage<float>(argv[optind++]);
    auto spgrSequence = make_shared<QI::SPGRSimple>(cin, prompt);
    if (verbose) cout << "Opening IR-SPGR file: " << argv[optind] << endl;
    auto irImg = QI::ReadVectorImage<float>(argv[optind++]);
    shared_ptr<QI::MPRAGE> irSequence;
    if (IR) {
        irSequence = make_shared<QI::IRSPGR>(cin, prompt);
    } else {
        irSequence = make_shared<QI::MPRAGE>(cin, prompt);
    }
    if (verbose) cout << *spgrSequence << endl << *irSequence << endl;
    auto apply = QI::ApplyF::New();
    hifi->setSequences(spgrSequence, irSequence);
    apply->SetAlgorithm(hifi);
    apply->SetOutputAllResiduals(all_residuals);
    apply->SetPoolsize(num_threads);
    apply->SetInput(0, spgrImg);
    apply->SetInput(1, irImg);
    if (mask)
        apply->SetMask(mask);
    if (verbose) {
        cout << "Processing..." << endl;
        auto monitor = QI::GenericMonitor::New();
        apply->AddObserver(itk::ProgressEvent(), monitor);
    }
    apply->Update();
    if (verbose) {
        cout << "Elapsed time was " << apply->GetTotalTime() << "s" << endl;
        cout << "Writing results files." << endl;
    }
    outPrefix = outPrefix + "HIFI_";

    QI::WriteImage(apply->GetOutput(0), outPrefix + "PD.nii");
    QI::WriteImage(apply->GetOutput(1), outPrefix + "T1.nii");
    QI::WriteImage(apply->GetOutput(2), outPrefix + "B1.nii");
    QI::WriteScaledImage(apply->GetResidualOutput(), apply->GetOutput(0), outPrefix + "residual.nii");
    if (all_residuals) {
        QI::WriteScaledVectorImage(apply->GetAllResidualsOutput(), apply->GetOutput(0), outPrefix + "all_residuals.nii");
    }
    if (verbose) cout << "Finished." << endl;
    return EXIT_SUCCESS;
}
<commit_msg>BUG: Was not respecting output extension environment variable.<commit_after>/*
 *  despot1hifi.cpp
 *
 *  Created by Tobias Wood on 17/10/2011.
 *  Copyright (c) 2011-2013 Tobias Wood.
 *
 *  Based on code by Sean Deoni
 *
 *  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/.
 *
 */

#include <getopt.h>
#include <iostream>
#include <Eigen/Dense>
#include <unsupported/Eigen/LevenbergMarquardt>
#include <unsupported/Eigen/NumericalDiff>

#include "itkImageFileReader.h"

#include "QI/Sequences/Sequences.h"
#include "QI/Util.h"
#include "QI/IO.h"
#include "Filters/ApplyAlgorithmFilter.h"

using namespace std;
using namespace Eigen;

//******************************************************************************
// Arguments / Usage
//******************************************************************************
const string usage {
"Usage is: qidespot1hifi [options] spgr_input ir-spgr_input\n\
\
Options:\n\
    --help, -h        : Print this message\n\
    --verbose, -v     : Print more information\n\
    --no-prompt, -n   : Suppress input prompts\n\
    --mprage, -M      : Use a generic MP-RAGE sequence, not GE IR-SPGR\n\
    --out, -o path    : Add a prefix to the output filenames\n\
    --mask, -m file   : Mask input with specified file\n\
    --thresh, -t n    : Threshold maps at PD < n\n\
    --clamp, -c n     : Clamp T1 between 0 and n\n\
    --its, -i N       : Max iterations for NLLS (default 4)\n\
    --resids, -r      : Write out per flip-angle residuals\n\
    --threads, -T N   : Use N threads (default=4, 0=hardware limit)\n"
};

static bool verbose = false, prompt = true, IR = true, all_residuals = false;
static size_t nIterations = 4, num_threads = 4;
static string outPrefix;
static double thresh = -numeric_limits<double>::infinity();
static double clamp_lo = -numeric_limits<double>::infinity(), clamp_hi = numeric_limits<double>::infinity();
static const struct option long_opts[] = {
    {"help", no_argument, 0, 'h'},
    {"verbose", no_argument, 0, 'v'},
    {"no-prompt", no_argument, 0, 'n'},
    {"mprage", no_argument, 0, 'M'},
    {"mask", required_argument, 0, 'm'},
    {"out", required_argument, 0, 'o'},
    {"thresh", required_argument, 0, 't'},
    {"clamp", required_argument, 0, 'c'},
    {"its", required_argument, 0, 'i'},
    {"resids", no_argument, 0, 'r'},
    {"threads", required_argument, 0, 'T'},
    {0, 0, 0, 0}
};
static const char *short_opts = "hvnMm:o:t:c:s:p:i:rT:";

// HIFI Algorithm - includes optimising B1
class HIFIFunctor : public DenseFunctor<double> {
    protected:
        const shared_ptr<QI::SPGRSimple> m_spgr;
        const shared_ptr<QI::MPRAGE> m_mprage;
        const ArrayXd m_data;

    public:
        HIFIFunctor(const shared_ptr<QI::SPGRSimple> spgr,
                    const shared_ptr<QI::MPRAGE> mprage,
                    const ArrayXd &data) :
            DenseFunctor<double>(3, spgr->size() + mprage->size()),
            m_spgr(spgr), m_mprage(mprage), m_data(data)
        {
            assert(static_cast<size_t>(m_data.rows()) == values());
        }

        int operator()(const Ref<VectorXd> &params, Ref<ArrayXd> diffs) const {
            eigen_assert(diffs.size() == values());

            ArrayXd s(values());
            s.head(m_spgr->size()) = QI::One_SPGR_Magnitude(m_spgr->flip(), m_spgr->TR(), params[0], params[1], params[2]);
            s.tail(m_mprage->size()) = QI::One_MPRAGE(m_mprage->flip()[0], m_mprage->TR(), m_mprage->m_Nseg, m_mprage->m_Nk0, m_mprage->m_TI, m_mprage->m_TD,
                                                      params[0], params[1], params[2], m_mprage->m_eta).cwiseAbs();
            diffs = s - m_data;
            return 0;
        }
};

class HIFIAlgo : public QI::ApplyF::Algorithm {
private:
    shared_ptr<QI::SPGRSimple> m_spgr;
    shared_ptr<QI::MPRAGE> m_mprage;
    size_t m_iterations = 15; // From tests this seems to be a sensible maximum number
    double m_thresh = -numeric_limits<double>::infinity();
    double m_lo = -numeric_limits<double>::infinity();
    double m_hi = numeric_limits<double>::infinity();
public:
    void setSequences(const shared_ptr<QI::SPGRSimple> &s, const shared_ptr<QI::MPRAGE> &m) { m_spgr = s; m_mprage = m;}
    void setIterations(size_t n) { m_iterations = n; }
    void setThreshold(double t) { m_thresh = t; }
    void setClamp(double lo, double hi) { m_lo = lo; m_hi = hi; }
    size_t numInputs() const override  { return 2; }
    size_t numConsts() const override  { return 0; }
    size_t numOutputs() const override { return 3; }
    size_t dataSize() const override   { return m_spgr->size() + m_mprage->size(); }
    const float &zero(const size_t i) const override { static float zero = 0; return zero; }

    virtual std::vector<float> defaultConsts() const override {
        // No constants for HIFI
        std::vector<float> def(0);
        return def;
    }

    virtual bool apply(const std::vector<TInput> &inputs, const std::vector<TConst> &, // No constants, remove name to silence compiler warnings
                       std::vector<TOutput> &outputs, TConst &residual,
                       TInput &resids, TIters &its) const override
    {
        Eigen::Map<const ArrayXf> spgr(inputs[0].GetDataPointer(), inputs[0].Size());
        Eigen::Map<const ArrayXf> irspgr(inputs[1].GetDataPointer(), inputs[1].Size());
        ArrayXf indata(dataSize()); indata << spgr, irspgr;
        const ArrayXd data = indata.cast<double>() / indata.abs().maxCoeff(); // Scale to make parameters roughly equal
        HIFIFunctor f(m_spgr, m_mprage, data);
        NumericalDiff<HIFIFunctor> nDiff(f);
        LevenbergMarquardt<NumericalDiff<HIFIFunctor>> lm(nDiff);
        // LevenbergMarquardt does not currently have a good interface, have to do things in steps
        lm.setMaxfev(m_iterations * (data.rows() + 1));
        VectorXd p(3); p << 10., 1., 1.; // Initial guess
        lm.minimize(p);
        ArrayXd r(indata.rows());
        f(p, r); // Get the residuals

        if (p[0] < m_thresh)
            p[0] = 0;
        else
            outputs[0] = p[0] * indata.abs().maxCoeff();
        outputs[1] = QI::clamp(p[1], m_lo, m_hi);
        outputs[2] = p[2];
        residual = sqrt(r.square().sum() / r.rows());
        ArrayXf rf = r.cast<float>();
        resids = itk::VariableLengthVector<float>(rf.data(), rf.rows());
        its = lm.iterations();
        return true;
    }
};

//******************************************************************************
// Main
//******************************************************************************
int main(int argc, char **argv) {
    Eigen::initParallel();
    QI::VolumeF::Pointer mask = ITK_NULLPTR;
    auto hifi = make_shared<HIFIAlgo>();
    int indexptr = 0, c;
    while ((c = getopt_long(argc, argv, short_opts, long_opts, &indexptr)) != -1) {
        switch (c) {
            case 'v': verbose = true; break;
            case 'n': prompt = false; break;
            case 'M': IR = false; break;
            case 'm':
                if (verbose) cout << "Opening mask file: " << optarg << endl;
                mask = QI::ReadImage(optarg);
                break;
            case 'o':
                outPrefix = optarg;
                if (verbose) cout << "Output prefix will be: " << outPrefix << endl;
                break;
            case 't': hifi->setThreshold(atof(optarg)); break;
            case 'c': hifi->setClamp(0, atof(optarg)); break;
            case 'i': hifi->setIterations(atoi(optarg)); break;
            case 'r': all_residuals = true; break;
            case 'T':
                num_threads = stoi(optarg);
                if (num_threads == 0)
                    num_threads = std::thread::hardware_concurrency();
                break;
            case 'h':
                cout << QI::GetVersion() << endl << usage << endl;
                return EXIT_SUCCESS;
            case '?': // getopt will print an error message
                return EXIT_FAILURE;
            default:
                cout << "Unhandled option " << string(1, c) << endl;
                return EXIT_FAILURE;
        }
    }
    if ((argc - optind) != 2) {
        cerr << "Incorrect number of arguments." << endl;
        cout << QI::GetVersion() << endl << usage << endl;
        return EXIT_FAILURE;
    }

    if (verbose) cout << "Opening SPGR file: " << argv[optind] << endl;
    auto spgrImg = QI::ReadVectorImage<float>(argv[optind++]);
    auto spgrSequence = make_shared<QI::SPGRSimple>(cin, prompt);
    if (verbose) cout << "Opening IR-SPGR file: " << argv[optind] << endl;
    auto irImg = QI::ReadVectorImage<float>(argv[optind++]);
    shared_ptr<QI::MPRAGE> irSequence;
    if (IR) {
        irSequence = make_shared<QI::IRSPGR>(cin, prompt);
    } else {
        irSequence = make_shared<QI::MPRAGE>(cin, prompt);
    }
    if (verbose) cout << *spgrSequence << endl << *irSequence << endl;
    auto apply = QI::ApplyF::New();
    hifi->setSequences(spgrSequence, irSequence);
    apply->SetAlgorithm(hifi);
    apply->SetOutputAllResiduals(all_residuals);
    apply->SetPoolsize(num_threads);
    apply->SetInput(0, spgrImg);
    apply->SetInput(1, irImg);
    if (mask)
        apply->SetMask(mask);
    if (verbose) {
        cout << "Processing..." << endl;
        auto monitor = QI::GenericMonitor::New();
        apply->AddObserver(itk::ProgressEvent(), monitor);
    }
    apply->Update();
    if (verbose) {
        cout << "Elapsed time was " << apply->GetTotalTime() << "s" << endl;
        cout << "Writing results files." << endl;
    }
    outPrefix = outPrefix + "HIFI_";

    QI::WriteImage(apply->GetOutput(0), outPrefix + "PD" + QI::OutExt());
    QI::WriteImage(apply->GetOutput(1), outPrefix + "T1" + QI::OutExt());
    QI::WriteImage(apply->GetOutput(2), outPrefix + "B1" + QI::OutExt());
    QI::WriteScaledImage(apply->GetResidualOutput(), apply->GetOutput(0), outPrefix + "residual"  + QI::OutExt());
    if (all_residuals) {
        QI::WriteScaledVectorImage(apply->GetAllResidualsOutput(), apply->GetOutput(0), outPrefix + "all_residuals" + QI::OutExt());
    }
    if (verbose) cout << "Finished." << endl;
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//Nicholas Gattuso 40007087
//referenced to-https://github.com/wishedeom/COMP371_A3/tree/master/COMP371_A3
//and from-https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection

#include <iostream>
#include <vector>
#include <math.h>
#include "CImg.h"
#include "sceneLoader.h"
#include "Camera.h"
#include "Sphere.h"
#include "Raytracing.h"
#include "Triangles.h"
#include "Plane.h"

using namespace std;

int main()
{
	cout << "main program for ray tracing" << endl;
	//for testing purpose

	//------------------------------------Read text file and get the object variables----------------------------------------------
	Scene loadtext("scene.txt");

	if (loadtext.getLoad()) { cout << "read succesfully" << endl; }
	else { cout << "Read failed" << endl; }

	//must add fetching of variables from scene instead of hardcoding it
	//-----------------------------------------Create camera object and image space-------------------------------------------------
	Camera camera(glm::vec3{ 0,0,0 }, 60, 1000, 1.33);

	//----------------------------------------------Create Sphere Object------------------------------------------------------------
	Sphere sphere1(glm::vec3{ 0,6,-40 }, 2, glm::vec3{ 0.1,0.5,0.5 }, glm::vec3{ 0.4, 0.6, 0.2 }, glm::vec3{ 0.2, 0.5, 0.5 }, 1);
	Sphere sphere2(glm::vec3{ 0,3,-40 }, 3, glm::vec3{ 0.3, 0.15, 0.2 }, glm::vec3{ 0.1, 0.22, 0.29 }, glm::vec3{ 0.2, 0.7, 0.2 }, 1);
	Sphere sphere3(glm::vec3{ 0, -3, -40 }, 5, glm::vec3{ 0.1, 0.15, 0.7 }, glm::vec3{ 0.8, 0.22, 0.29 }, glm::vec3{ 0.2, 0.7, 0.8 }, 1);

	//place sphere objects in a vector
	std::vector<Sphere> sphereObjects;
	sphereObjects.emplace_back(sphere1);
	sphereObjects.emplace_back(sphere2);
	sphereObjects.emplace_back(sphere3);

	bool sphereIntersect = false;

	//----------------------------------------------Create Triangle Object------------------------------------------------------------
	Triangle triangle1(glm::vec3{ 1,7,-40 }, glm::vec3{ 1,5,-40 }, glm::vec3{ 5,6,-40 }, glm::vec3{ 0.5,0.2,0.7 }, glm::vec3{ 0.2, 0.4, 0.2 }, glm::vec3{ 0.1, 0.1, 0.2 }, 0.5);

	//place sphere objects in a vector
	std::vector<Triangle> triangleObjects;
	triangleObjects.emplace_back(triangle1);

	bool triIntersect = false;

	//---------------------------------------------------Creating Plane Object----------------------------------------------
	Plane plane(glm::vec3{ 0,1,0 }, glm::vec3{ 0,-5,0 }, glm::vec3{ 0.8,0.8,0.8 }, glm::vec3{ 0.1,0.1,0.1 },
		glm::vec3{ 0.7,0.7,0.7 }, 6);
	bool planeInter = false;

	//NEED TO DO
	//Add the other objects (triangles, objs, plane, light)
	//Fix the scene to get the objects from the scene instead

	//--------------------------------------------------Define the Image-------------------------------------------------------
	//Creates an image with three channels and sets it to black
	cimg_library::CImg<float> image(camera.getWidth(), camera.getHeight(), 1, 3, 0);

	//NEED TO DO
	//Go through each pixel in the image -> make a loop throughout the image, for every pixel do the following:
	float imageWidth = camera.getWidth(); float imageHeight = camera.getHeight();
	float aspectRatio = imageWidth / imageHeight;
	glm::vec3 camPos = camera.getPosition();

	for (int h = 0; h <= imageHeight - 1; h++) //loop through every height column
	{
		for (int w = 0; w <= imageWidth - 1; w++) //loop through every width row
		{
			//reset boolean values for every pixel
			sphereIntersect = false;
			triIntersect = false;
			planeInter = false;

			//get Camera space
			float pX = (2 * ((w + 0.5) / imageWidth) - 1) * tan((camera.getFOV()) / 2 * 3.14159 / 180) * aspectRatio;
			float pY = (1 - 2 * ((h + 0.5) / imageHeight)) * tan((camera.getFOV()) / 2 * 3.14159 / 180);
			glm::vec3 rayDirection = glm::vec3{ pX, pY, -1 } - camera.getPosition();
			rayDirection = glm::normalize(rayDirection);

			//get a ray
			//Raytray ray = camera.rayPixel(w, h); //ray receives the point (w,h) and the direction

			//calculate distance to know how far to check
			//glm::vec2 distance{(w - camPos.x), (h - camPos.y)};
			//float dista = sqrt((distance.x)*(distance.x) + (distance.y)*(distance.y));

			glm::vec3 colour{ 0.0, 0.0, 0.0 };

			//-------toss ray and check for intersection-----
			//for spheres
			float nearestSphere = 1000000; int nearestSphereIndex;
			for (int i = 0; i <= sphereObjects.size() - 1; i++)
			{
				if (sphereObjects[i].sphereInter(camera.getPosition(), rayDirection)) //if it intersects
				{
					sphereIntersect = true;
					if (sphereObjects[i].getInterDis() <= nearestSphere)
					{
						nearestSphere = sphereObjects[i].getInterDis();
						nearestSphereIndex = i;
					}
				}
			}

			//for triangles
			float nearestTri = 1000000; int nearestTriIndex;
			for (int i = 0; i <= triangleObjects.size() - 1; i++)
			{
				if (triangleObjects[i].triInter(camera.getPosition(), rayDirection, triangleObjects[i].getVertex1(),
					triangleObjects[i].getVertex2(), triangleObjects[i].getVertex3())) //if it intersects
				{
					triIntersect = true;
					if (triangleObjects[i].getInterDis() <= nearestTri)
					{
						nearestTri = triangleObjects[i].getInterDis();
						nearestTriIndex = i;
					}
				}
			}

			//for plane
			planeInter = plane.planeInter(plane.getNOR(), plane.getPosition(), camera.getPosition(), rayDirection);

			//------------------------------------------Check for nearest----------------------------------------
			//----------if all three objects are intersected------------------
			if (triIntersect && sphereIntersect && planeInter)
			{
				if (nearestSphere <= nearestTri) //case if sphere is nearest
				{
					if (nearestSphere <= plane.getInterDis()) { colour = sphereObjects[nearestSphereIndex].getAmbient(); }
				}
				else if (nearestTri <= nearestSphere) //case if triangle is nearest
				{
					if (nearestTri <= plane.getInterDis()){ colour = triangleObjects[nearestTriIndex].getAmbient(); }
				}
				else { colour = plane.getAmbient(); }
			}
			//-------if only tri and sphere are intersected------------
			else if (triIntersect && sphereIntersect)
			{
				if (nearestTri <= nearestSphere) //case if sphere is nearest
				{
					colour = sphereObjects[nearestSphereIndex].getAmbient();
				}
				else { colour = triangleObjects[nearestTriIndex].getAmbient(); }
			}
			//-------if only tri and plane are intersected-------------
			else if (triIntersect && planeInter)
			{
				if (plane.getInterDis() <= nearestTri) //case if plane is nearest
				{
					colour = plane.getAmbient();
				}
				else { colour = triangleObjects[nearestTriIndex].getAmbient(); }
			}
			//-------if only sphere and plane are intersected---------
			else if (sphereIntersect && planeInter)
			{
				if (plane.getInterDis() <= nearestSphere) //case if plane is nearest
				{
					colour = plane.getAmbient();
				}
				else { colour = sphereObjects[nearestSphereIndex].getAmbient(); }
			}
			//---------only 1 intersection occured-------
			else if (triIntersect){ colour = triangleObjects[nearestTriIndex].getAmbient(); }
			else if (sphereIntersect) { colour = sphereObjects[nearestSphereIndex].getAmbient(); }
			else if (planeInter){ colour = plane.getAmbient();}

			//Store the colour of the pixel
			float color[3]{ colour.x, colour.y, colour.z };
			image.draw_point(w, h, color);
		}
	}

	//-------------------------------------------------Save image---------------------------------------------------------
	//Save out the image in BMP format. Pixel values must be in the range [0,255]
	image.normalize(0, 255);
	image.save("render.bmp");

	//Display the rendered image on screen
	cimg_library::CImgDisplay main_disp(image, "Render");
	while (!main_disp.is_closed())
		main_disp.wait();

	return 0;
}<commit_msg>created the light object<commit_after>//Nicholas Gattuso 40007087
//referenced to-https://github.com/wishedeom/COMP371_A3/tree/master/COMP371_A3
//and from-https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection

#include <iostream>
#include <vector>
#include <math.h>
#include "CImg.h"
#include "sceneLoader.h"
#include "Camera.h"
#include "Sphere.h"
#include "Raytracing.h"
#include "Triangles.h"
#include "Plane.h"
#include "Light.h"

using namespace std;

int main()
{
	cout << "main program for ray tracing" << endl;
	//for testing purpose

	//------------------------------------Read text file and get the object variables----------------------------------------------
	Scene loadtext("scene.txt");

	if (loadtext.getLoad()) { cout << "read succesfully" << endl; }
	else { cout << "Read failed" << endl; }

	//must add fetching of variables from scene instead of hardcoding it
	//-----------------------------------------Create camera object and image space-------------------------------------------------
	Camera camera(glm::vec3{ 0,0,0 }, 60, 1000, 1.33);

	//----------------------------------------------Create Sphere Object------------------------------------------------------------
	Sphere sphere1(glm::vec3{ 0,6,-40 }, 2, glm::vec3{ 0.1,0.5,0.5 }, glm::vec3{ 0.4, 0.6, 0.2 }, glm::vec3{ 0.2, 0.5, 0.5 }, 1);
	Sphere sphere2(glm::vec3{ 0,3,-40 }, 3, glm::vec3{ 0.3, 0.15, 0.2 }, glm::vec3{ 0.1, 0.22, 0.29 }, glm::vec3{ 0.2, 0.7, 0.2 }, 1);
	Sphere sphere3(glm::vec3{ 0, -3, -40 }, 5, glm::vec3{ 0.1, 0.15, 0.7 }, glm::vec3{ 0.8, 0.22, 0.29 }, glm::vec3{ 0.2, 0.7, 0.8 }, 1);

	//place sphere objects in a vector
	std::vector<Sphere> sphereObjects;
	sphereObjects.emplace_back(sphere1);
	sphereObjects.emplace_back(sphere2);
	sphereObjects.emplace_back(sphere3);

	bool sphereIntersect = false;

	//----------------------------------------------Create Triangle Object------------------------------------------------------------
	Triangle triangle1(glm::vec3{ 1,7,-40 }, glm::vec3{ 1,5,-40 }, glm::vec3{ 5,6,-40 }, glm::vec3{ 0.5,0.2,0.7 }, glm::vec3{ 0.2, 0.4, 0.2 }, glm::vec3{ 0.1, 0.1, 0.2 }, 0.5);

	//place sphere objects in a vector
	std::vector<Triangle> triangleObjects;
	triangleObjects.emplace_back(triangle1);

	bool triIntersect = false;

	//---------------------------------------------------Creating Plane Object----------------------------------------------
	Plane plane(glm::vec3{ 0,1,0 }, glm::vec3{ 0,-5,0 }, glm::vec3{ 0.8,0.8,0.8 }, glm::vec3{ 0.1,0.1,0.1 },
		glm::vec3{ 0.7,0.7,0.7 }, 6);
	bool planeInter = false;

	//----------------------------------------------Creating the Light Object---------------------------------------------
	Light light(glm::vec3{ 15, 12, -3 }, glm::vec3{ 0.3, 0.9, 0.9 });

	//NEED TO DO
	//Add the other objects (triangles, objs, plane, light)
	//Fix the scene to get the objects from the scene instead

	//--------------------------------------------------Define the Image-------------------------------------------------------
	//Creates an image with three channels and sets it to black
	cimg_library::CImg<float> image(camera.getWidth(), camera.getHeight(), 1, 3, 0);

	//NEED TO DO
	//Go through each pixel in the image -> make a loop throughout the image, for every pixel do the following:
	float imageWidth = camera.getWidth(); float imageHeight = camera.getHeight();
	float aspectRatio = imageWidth / imageHeight;
	glm::vec3 camPos = camera.getPosition();

	for (int h = 0; h <= imageHeight - 1; h++) //loop through every height column
	{
		for (int w = 0; w <= imageWidth - 1; w++) //loop through every width row
		{
			//reset boolean values for every pixel
			sphereIntersect = false;
			triIntersect = false;
			planeInter = false;

			//get Camera space
			float pX = (2 * ((w + 0.5) / imageWidth) - 1) * tan((camera.getFOV()) / 2 * 3.14159 / 180) * aspectRatio;
			float pY = (1 - 2 * ((h + 0.5) / imageHeight)) * tan((camera.getFOV()) / 2 * 3.14159 / 180);
			glm::vec3 rayDirection = glm::vec3{ pX, pY, -1 } - camera.getPosition();
			rayDirection = glm::normalize(rayDirection);

			//get a ray
			//Raytray ray = camera.rayPixel(w, h); //ray receives the point (w,h) and the direction

			//calculate distance to know how far to check
			//glm::vec2 distance{(w - camPos.x), (h - camPos.y)};
			//float dista = sqrt((distance.x)*(distance.x) + (distance.y)*(distance.y));

			glm::vec3 colour{ 0.0, 0.0, 0.0 };

			//-------toss ray and check for intersection-----
			//for spheres
			float nearestSphere = 1000000; int nearestSphereIndex;
			for (int i = 0; i <= sphereObjects.size() - 1; i++)
			{
				if (sphereObjects[i].sphereInter(camera.getPosition(), rayDirection)) //if it intersects
				{
					sphereIntersect = true;
					if (sphereObjects[i].getInterDis() <= nearestSphere)
					{
						nearestSphere = sphereObjects[i].getInterDis();
						nearestSphereIndex = i;
					}
				}
			}

			//for triangles
			float nearestTri = 1000000; int nearestTriIndex;
			for (int i = 0; i <= triangleObjects.size() - 1; i++)
			{
				if (triangleObjects[i].triInter(camera.getPosition(), rayDirection, triangleObjects[i].getVertex1(),
					triangleObjects[i].getVertex2(), triangleObjects[i].getVertex3())) //if it intersects
				{
					triIntersect = true;
					if (triangleObjects[i].getInterDis() <= nearestTri)
					{
						nearestTri = triangleObjects[i].getInterDis();
						nearestTriIndex = i;
					}
				}
			}

			//for plane
			planeInter = plane.planeInter(plane.getNOR(), plane.getPosition(), camera.getPosition(), rayDirection);

			//------------------------------------------Check for nearest----------------------------------------
			//----------if all three objects are intersected------------------
			if (triIntersect && sphereIntersect && planeInter)
			{
				if (nearestSphere <= nearestTri) //case if sphere is nearest
				{
					if (nearestSphere <= plane.getInterDis()) { colour = sphereObjects[nearestSphereIndex].getAmbient(); }
				}
				else if (nearestTri <= nearestSphere) //case if triangle is nearest
				{
					if (nearestTri <= plane.getInterDis()){ colour = triangleObjects[nearestTriIndex].getAmbient(); }
				}
				else { colour = plane.getAmbient(); }
			}
			//-------if only tri and sphere are intersected------------
			else if (triIntersect && sphereIntersect)
			{
				if (nearestTri <= nearestSphere) //case if sphere is nearest
				{
					colour = sphereObjects[nearestSphereIndex].getAmbient();
				}
				else { colour = triangleObjects[nearestTriIndex].getAmbient(); }
			}
			//-------if only tri and plane are intersected-------------
			else if (triIntersect && planeInter)
			{
				if (plane.getInterDis() <= nearestTri) //case if plane is nearest
				{
					colour = plane.getAmbient();
				}
				else { colour = triangleObjects[nearestTriIndex].getAmbient(); }
			}
			//-------if only sphere and plane are intersected---------
			else if (sphereIntersect && planeInter)
			{
				if (plane.getInterDis() <= nearestSphere) //case if plane is nearest
				{
					colour = plane.getAmbient();
				}
				else { colour = sphereObjects[nearestSphereIndex].getAmbient(); }
			}
			//---------only 1 intersection occured-------
			else if (triIntersect){ colour = triangleObjects[nearestTriIndex].getAmbient(); }
			else if (sphereIntersect) { colour = sphereObjects[nearestSphereIndex].getAmbient(); }
			else if (planeInter){ colour = plane.getAmbient();}

			//Store the colour of the pixel
			float color[3]{ colour.x, colour.y, colour.z };
			image.draw_point(w, h, color);
		}
	}

	//-------------------------------------------------Save image---------------------------------------------------------
	//Save out the image in BMP format. Pixel values must be in the range [0,255]
	image.normalize(0, 255);
	image.save("render.bmp");

	//Display the rendered image on screen
	cimg_library::CImgDisplay main_disp(image, "Render");
	while (!main_disp.is_closed())
		main_disp.wait();

	return 0;
}<|endoftext|>


<commit_before>//Copyright (C) 2011 by Jason L. McKesson
//This file is licensed by the MIT License.

#include "glutil/MatrixStack.h"
#include <glm/gtc/matrix_transform.hpp>
#include <math.h>

namespace glutil
{
	void MatrixStack::Rotate( const glm::vec3 axis, float angDegCCW )
	{
		m_currMatrix = glm::rotate(m_currMatrix, angDegCCW, axis);
	}

	void MatrixStack::RotateRadians( const glm::vec3 axisOfRotation, float angRadCCW )
	{
		float fCos = cosf(angRadCCW);
		float fInvCos = 1.0f - fCos;
		float fSin = sinf(angRadCCW);
		float fInvSin = 1.0f - fSin;

		glm::vec3 axis = glm::normalize(axisOfRotation);

		glm::mat4 theMat(1.0f);
		theMat[0].x = (axis.x * axis.x) + ((1 - axis.x * axis.x) * fCos);
		theMat[1].x = axis.x * axis.y * (fInvCos) - (axis.z * fSin);
		theMat[2].x = axis.x * axis.z * (fInvCos) + (axis.y * fSin);

		theMat[0].y = axis.x * axis.y * (fInvCos) + (axis.z * fSin);
		theMat[1].y = (axis.y * axis.y) + ((1 - axis.y * axis.y) * fCos);
		theMat[2].y = axis.y * axis.z * (fInvCos) - (axis.x * fSin);

		theMat[0].z = axis.x * axis.z * (fInvCos) - (axis.y * fSin);
		theMat[1].z = axis.y * axis.z * (fInvCos) + (axis.x * fSin);
		theMat[2].z = (axis.z * axis.z) + ((1 - axis.z * axis.z) * fCos);
		m_currMatrix *= theMat;
	}

	void MatrixStack::RotateX( float angDegCCW )
	{
		Rotate(glm::vec3(1.0f, 0.0f, 0.0f), angDegCCW);
	}

	void MatrixStack::RotateY( float angDegCCW )
	{
		Rotate(glm::vec3(0.0f, 1.0f, 0.0f), angDegCCW);
	}

	void MatrixStack::RotateZ( float angDegCCW )
	{
		Rotate(glm::vec3(0.0f, 0.0f, 1.0f), angDegCCW);
	}

	void MatrixStack::Scale( const glm::vec3 &scaleVec )
	{
		m_currMatrix = glm::scale(m_currMatrix, scaleVec);
	}

	void MatrixStack::Translate( const glm::vec3 &offsetVec )
	{
		m_currMatrix = glm::translate(m_currMatrix, offsetVec);
	}

	void MatrixStack::Perspective( float degFOV, float aspectRatio, float zNear, float zFar )
	{
		m_currMatrix *= glm::perspective(degFOV, aspectRatio, zNear, zFar);
	}

	void MatrixStack::Orthographic( float left, float right, float bottom, float top,
		float zNear, float zFar )
	{
		m_currMatrix *= glm::ortho(left, right, bottom, top, zNear, zFar);
	}

	void MatrixStack::PixelPerfectOrtho( glm::ivec2 size, glm::vec2 depthRange, bool isTopLeft /*= true*/ )
	{
		if(isTopLeft)
		{
			Translate(-1.0f, 1.0f, (depthRange.x + depthRange.y) / 2.0f);
			Scale(2.0f / size.x, -2.0f / size.y, 1.0f);
		}
		else
		{
			Translate(-1.0f, -1.0f, (depthRange.x + depthRange.y) / 2.0f);
			Scale(2.0f / size.x, 2.0f / size.y, 2.0f / (depthRange.y - depthRange.x));
		}
	}

	void MatrixStack::LookAt( const glm::vec3 &cameraPos, const glm::vec3 &lookatPos, const glm::vec3 &upDir )
	{
		m_currMatrix *= glm::lookAt(cameraPos, lookatPos, upDir);
	}

	void MatrixStack::ApplyMatrix( const glm::mat4 &theMatrix )
	{
		m_currMatrix *= theMatrix;
	}

	void MatrixStack::SetMatrix( const glm::mat4 &theMatrix )
	{
		m_currMatrix = theMatrix;
	}

	void MatrixStack::SetIdentity()
	{
		m_currMatrix = glm::mat4(1.0f);
	}
}

<commit_msg>MatrixStack: convert angle to radians before applying rotation.<commit_after>//Copyright (C) 2011 by Jason L. McKesson
//This file is licensed by the MIT License.

#include "glutil/MatrixStack.h"
#include <glm/gtc/matrix_transform.hpp>
#include <math.h>

namespace glutil
{
	void MatrixStack::Rotate( const glm::vec3 axis, float angDegCCW )
	{
    m_currMatrix = glm::rotate(m_currMatrix, (3.14159f * 2.0f / 360.0f) * angDegCCW, axis);
	}

	void MatrixStack::RotateRadians( const glm::vec3 axisOfRotation, float angRadCCW )
	{
		float fCos = cosf(angRadCCW);
		float fInvCos = 1.0f - fCos;
		float fSin = sinf(angRadCCW);
		float fInvSin = 1.0f - fSin;

		glm::vec3 axis = glm::normalize(axisOfRotation);

		glm::mat4 theMat(1.0f);
		theMat[0].x = (axis.x * axis.x) + ((1 - axis.x * axis.x) * fCos);
		theMat[1].x = axis.x * axis.y * (fInvCos) - (axis.z * fSin);
		theMat[2].x = axis.x * axis.z * (fInvCos) + (axis.y * fSin);

		theMat[0].y = axis.x * axis.y * (fInvCos) + (axis.z * fSin);
		theMat[1].y = (axis.y * axis.y) + ((1 - axis.y * axis.y) * fCos);
		theMat[2].y = axis.y * axis.z * (fInvCos) - (axis.x * fSin);

		theMat[0].z = axis.x * axis.z * (fInvCos) - (axis.y * fSin);
		theMat[1].z = axis.y * axis.z * (fInvCos) + (axis.x * fSin);
		theMat[2].z = (axis.z * axis.z) + ((1 - axis.z * axis.z) * fCos);
		m_currMatrix *= theMat;
	}

	void MatrixStack::RotateX( float angDegCCW )
	{
		Rotate(glm::vec3(1.0f, 0.0f, 0.0f), angDegCCW);
	}

	void MatrixStack::RotateY( float angDegCCW )
	{
		Rotate(glm::vec3(0.0f, 1.0f, 0.0f), angDegCCW);
	}

	void MatrixStack::RotateZ( float angDegCCW )
	{
		Rotate(glm::vec3(0.0f, 0.0f, 1.0f), angDegCCW);
	}

	void MatrixStack::Scale( const glm::vec3 &scaleVec )
	{
		m_currMatrix = glm::scale(m_currMatrix, scaleVec);
	}

	void MatrixStack::Translate( const glm::vec3 &offsetVec )
	{
		m_currMatrix = glm::translate(m_currMatrix, offsetVec);
	}

	void MatrixStack::Perspective( float degFOV, float aspectRatio, float zNear, float zFar )
	{
		m_currMatrix *= glm::perspective(degFOV, aspectRatio, zNear, zFar);
	}

	void MatrixStack::Orthographic( float left, float right, float bottom, float top,
		float zNear, float zFar )
	{
		m_currMatrix *= glm::ortho(left, right, bottom, top, zNear, zFar);
	}

	void MatrixStack::PixelPerfectOrtho( glm::ivec2 size, glm::vec2 depthRange, bool isTopLeft /*= true*/ )
	{
		if(isTopLeft)
		{
			Translate(-1.0f, 1.0f, (depthRange.x + depthRange.y) / 2.0f);
			Scale(2.0f / size.x, -2.0f / size.y, 1.0f);
		}
		else
		{
			Translate(-1.0f, -1.0f, (depthRange.x + depthRange.y) / 2.0f);
			Scale(2.0f / size.x, 2.0f / size.y, 2.0f / (depthRange.y - depthRange.x));
		}
	}

	void MatrixStack::LookAt( const glm::vec3 &cameraPos, const glm::vec3 &lookatPos, const glm::vec3 &upDir )
	{
		m_currMatrix *= glm::lookAt(cameraPos, lookatPos, upDir);
	}

	void MatrixStack::ApplyMatrix( const glm::mat4 &theMatrix )
	{
		m_currMatrix *= theMatrix;
	}

	void MatrixStack::SetMatrix( const glm::mat4 &theMatrix )
	{
		m_currMatrix = theMatrix;
	}

	void MatrixStack::SetIdentity()
	{
		m_currMatrix = glm::mat4(1.0f);
	}
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once
#include <core/sstring.hh>
#include <boost/lexical_cast.hpp>
#include "exceptions/exceptions.hh"
#include "json.hh"

class schema;

class caching_options {
    // For Origin, the default value for the row is "NONE". However, since our
    // row_cache will cache both keys and rows, we will default to ALL.
    //
    // FIXME: We don't yet make any changes to our caching policies based on
    // this (and maybe we shouldn't)
    static constexpr auto default_key = "ALL";
    static constexpr auto default_row = "ALL";

    sstring _key_cache;
    sstring _row_cache;
    caching_options(sstring k, sstring r) : _key_cache(k), _row_cache(r) {
        if ((k != "ALL") && (k != "NONE")) {
            throw exceptions::configuration_exception("Invalid key value: " + k);
        }

        try {
            boost::lexical_cast<unsigned long>(r);
        } catch (boost::bad_lexical_cast& e) {
            if ((r != "ALL") && (r != "NONE")) {
                throw exceptions::configuration_exception("Invalid key value: " + k);
            }
        }
    }

    friend class schema;
    caching_options() : _key_cache(default_key), _row_cache(default_row) {}
public:

    sstring to_sstring() const {
        return json::to_json(std::map<sstring, sstring>({{ "keys", _key_cache }, { "rows_per_partition", _row_cache }}));
    }

    static caching_options from_sstring(const sstring& str) {
        auto map = json::to_map(str);
        if (map.size() > 2) {
            throw exceptions::configuration_exception("Invalid map: " + str);
        }
        sstring k;
        sstring r;
        if (map.count("keys")) {
            k = map.at("keys");
        } else {
            k = default_key;
        }

        if (map.count("rows_per_partition")) {
            r = map.at("rows_per_partition");
        } else {
            r = default_row;
        }
        return caching_options(k, r);
    }
};

<commit_msg>avoid exception when processing caching_options<commit_after>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once
#include <core/sstring.hh>
#include <boost/lexical_cast.hpp>
#include "exceptions/exceptions.hh"
#include "json.hh"

class schema;

class caching_options {
    // For Origin, the default value for the row is "NONE". However, since our
    // row_cache will cache both keys and rows, we will default to ALL.
    //
    // FIXME: We don't yet make any changes to our caching policies based on
    // this (and maybe we shouldn't)
    static constexpr auto default_key = "ALL";
    static constexpr auto default_row = "ALL";

    sstring _key_cache;
    sstring _row_cache;
    caching_options(sstring k, sstring r) : _key_cache(k), _row_cache(r) {
        if ((k != "ALL") && (k != "NONE")) {
            throw exceptions::configuration_exception("Invalid key value: " + k);
        }

        if ((r == "ALL") || (r == "NONE")) {
            return;
        } else {
            try {
                boost::lexical_cast<unsigned long>(r);
            } catch (boost::bad_lexical_cast& e) {
                throw exceptions::configuration_exception("Invalid key value: " + r);
            }
        }
    }

    friend class schema;
    caching_options() : _key_cache(default_key), _row_cache(default_row) {}
public:

    sstring to_sstring() const {
        return json::to_json(std::map<sstring, sstring>({{ "keys", _key_cache }, { "rows_per_partition", _row_cache }}));
    }

    static caching_options from_sstring(const sstring& str) {
        auto map = json::to_map(str);
        if (map.size() > 2) {
            throw exceptions::configuration_exception("Invalid map: " + str);
        }
        sstring k;
        sstring r;
        if (map.count("keys")) {
            k = map.at("keys");
        } else {
            k = default_key;
        }

        if (map.count("rows_per_partition")) {
            r = map.at("rows_per_partition");
        } else {
            r = default_row;
        }
        return caching_options(k, r);
    }
};

<|endoftext|>