<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "Parser.h"

#include <utility>
#include <cassert>

#include "MediaLibrary.h"
#include "ParserWorker.h"
#include "parser/Task.h"
#include "logging/Logger.h"

namespace medialibrary
{
namespace parser
{

Parser::Parser( MediaLibrary* ml )
    : m_ml( ml )
    , m_callback( ml->getCb() )
    , m_opToDo( 0 )
    , m_opDone( 0 )
    , m_percent( 0 )
{
}

Parser::~Parser()
{
    stop();
}

void Parser::addService( ServicePtr service )
{
    auto worker = std::unique_ptr<Worker>( new Worker );
    if ( worker->initialize( m_ml, this, std::move( service ) ) == false )
        return;
    m_serviceWorkers.push_back( std::move( worker ) );
}

void Parser::parse( std::shared_ptr<Task> task )
{
    if ( m_serviceWorkers.empty() == true )
        return;
    assert( task != nullptr );
    m_serviceWorkers[0]->parse( std::move( task ) );
    ++m_opToDo;
    updateStats();
}

void Parser::start()
{
    assert( m_serviceWorkers.size() == 3 );
    restore();
}

void Parser::pause()
{
    for ( auto& s : m_serviceWorkers )
        s->pause();
}

void Parser::resume()
{
    for ( auto& s : m_serviceWorkers )
        s->resume();
}

void Parser::stop()
{
    for ( auto& s : m_serviceWorkers )
    {
        s->signalStop();
    }
    for ( auto& s : m_serviceWorkers )
    {
        s->stop();
    }
}

void Parser::flush()
{
    for ( auto& s : m_serviceWorkers )
        s->flush();
    m_opToDo = 0;
    m_opDone = 0;
}

void Parser::prepareRescan()
{
    pause();
    flush();
}

void Parser::rescan()
{
    restart();
    restore();
    resume();
}

void Parser::restart()
{
    for ( auto& s : m_serviceWorkers )
        s->restart();
}

void Parser::restore()
{
    if ( m_serviceWorkers.empty() == true )
        return;
    auto tasks = Task::fetchUncompleted( m_ml );
    if ( tasks.empty() == true )
    {
        LOG_DEBUG( "No task to resume." );
        return;
    }
    LOG_INFO( "Resuming parsing on ", tasks.size(), " tasks" );
    m_opToDo += tasks.size();
    updateStats();
    m_serviceWorkers[0]->parse( std::move( tasks ) );
}

void Parser::refreshTaskList()
{
    /*
     * We need to do this in various steps:
     * - Pausing the workers after their currently running task
     * - Flushing their task list
     * - Restoring the task list from DB
     * - Resuming the workers
     */
    pause();
    flush();
    restore();
    resume();
}

void Parser::updateStats()
{
    if ( m_opDone == 0 && m_opToDo > 0 && m_chrono == decltype(m_chrono){})
        m_chrono = std::chrono::steady_clock::now();
    auto percent = m_opToDo > 0 ? ( m_opDone * 100 / m_opToDo ) : 0;
    assert( m_opToDo >= m_opDone );
    if ( percent != m_percent )
    {
        m_percent = percent;
        LOG_DEBUG( "Updating progress: ", percent );
        m_callback->onParsingStatsUpdated( m_percent );
        if ( m_percent == 100 )
        {
            auto duration = std::chrono::steady_clock::now() - m_chrono;
            LOG_VERBOSE( "Finished all parsing operations in ",
                       std::chrono::duration_cast<std::chrono::milliseconds>( duration ).count(), "ms" );
            m_chrono = decltype(m_chrono){};
        }
    }
}

void Parser::done( std::shared_ptr<Task> t, Status status )
{
    auto serviceIdx = t->goToNextService();

    if ( status == Status::TemporaryUnavailable ||
         status == Status::Fatal ||
         status == Status::Discarded ||
         t->isCompleted() )
    {
        ++m_opDone;

        updateStats();
        // We create a separate task for refresh, which doesn't count toward
        // (mrl,parent_playlist) uniqueness. In order to allow for a subsequent
        // refresh of the same file, we remove it once the refresh is complete.
        // In case the status was `Discarded`, the task was already deleted from
        // the database.
        if ( t->isRefresh() == true )
            Task::destroy( m_ml, t->id() );
        return;
    }
    if ( status == Status::Requeue )
    {
        // The retry_count is mostly handled when fetching the remaining tasks
        // from the database. However, when requeuing, it all happens at runtime
        // in the C++ code, so we also need to ensure we're not requeuing tasks
        // forever.
        if ( t->retryCount() >= parser::MaxNbRetries )
        {
            ++m_opDone;
            updateStats();
            return;
        }
        t->resetCurrentService();
        serviceIdx = 0;
    }

    // If some services declined to parse the file, start over again.
    assert( serviceIdx < m_serviceWorkers.size() );
    updateStats();
    m_serviceWorkers[serviceIdx]->parse( std::move( t ) );
}

void Parser::onIdleChanged( bool idle )
{
    // If any parser service is not idle, then the global parser state is active
    if ( idle == false )
    {
        m_ml->onParserIdleChanged( false );
        return;
    }
    // Otherwise the parser is idle when all services are idle
    for ( const auto& s : m_serviceWorkers )
    {
        // We're switching a service from "not idle" to "idle" here, so as far as the medialibrary
        // is concerned the parser is still "not idle". In case a single parser service isn't
        // idle, no need to trigger a change to the medialibrary.
        if ( s->isIdle() == false )
            return;
    }
    m_ml->onParserIdleChanged( true );
}

}
}
<commit_msg>Parser: Fix linking tasks retry handling<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "Parser.h"

#include <utility>
#include <cassert>

#include "MediaLibrary.h"
#include "ParserWorker.h"
#include "parser/Task.h"
#include "logging/Logger.h"

namespace medialibrary
{
namespace parser
{

Parser::Parser( MediaLibrary* ml )
    : m_ml( ml )
    , m_callback( ml->getCb() )
    , m_opToDo( 0 )
    , m_opDone( 0 )
    , m_percent( 0 )
{
}

Parser::~Parser()
{
    stop();
}

void Parser::addService( ServicePtr service )
{
    auto worker = std::unique_ptr<Worker>( new Worker );
    if ( worker->initialize( m_ml, this, std::move( service ) ) == false )
        return;
    m_serviceWorkers.push_back( std::move( worker ) );
}

void Parser::parse( std::shared_ptr<Task> task )
{
    if ( m_serviceWorkers.empty() == true )
        return;
    assert( task != nullptr );
    m_serviceWorkers[0]->parse( std::move( task ) );
    ++m_opToDo;
    updateStats();
}

void Parser::start()
{
    assert( m_serviceWorkers.size() == 3 );
    restore();
}

void Parser::pause()
{
    for ( auto& s : m_serviceWorkers )
        s->pause();
}

void Parser::resume()
{
    for ( auto& s : m_serviceWorkers )
        s->resume();
}

void Parser::stop()
{
    for ( auto& s : m_serviceWorkers )
    {
        s->signalStop();
    }
    for ( auto& s : m_serviceWorkers )
    {
        s->stop();
    }
}

void Parser::flush()
{
    for ( auto& s : m_serviceWorkers )
        s->flush();
    m_opToDo = 0;
    m_opDone = 0;
}

void Parser::prepareRescan()
{
    pause();
    flush();
}

void Parser::rescan()
{
    restart();
    restore();
    resume();
}

void Parser::restart()
{
    for ( auto& s : m_serviceWorkers )
        s->restart();
}

void Parser::restore()
{
    if ( m_serviceWorkers.empty() == true )
        return;
    auto tasks = Task::fetchUncompleted( m_ml );
    if ( tasks.empty() == true )
    {
        LOG_DEBUG( "No task to resume." );
        return;
    }
    LOG_INFO( "Resuming parsing on ", tasks.size(), " tasks" );
    m_opToDo += tasks.size();
    updateStats();
    m_serviceWorkers[0]->parse( std::move( tasks ) );
}

void Parser::refreshTaskList()
{
    /*
     * We need to do this in various steps:
     * - Pausing the workers after their currently running task
     * - Flushing their task list
     * - Restoring the task list from DB
     * - Resuming the workers
     */
    pause();
    flush();
    restore();
    resume();
}

void Parser::updateStats()
{
    if ( m_opDone == 0 && m_opToDo > 0 && m_chrono == decltype(m_chrono){})
        m_chrono = std::chrono::steady_clock::now();
    auto percent = m_opToDo > 0 ? ( m_opDone * 100 / m_opToDo ) : 0;
    assert( m_opToDo >= m_opDone );
    if ( percent != m_percent )
    {
        m_percent = percent;
        LOG_DEBUG( "Updating progress: ", percent );
        m_callback->onParsingStatsUpdated( m_percent );
        if ( m_percent == 100 )
        {
            auto duration = std::chrono::steady_clock::now() - m_chrono;
            LOG_VERBOSE( "Finished all parsing operations in ",
                       std::chrono::duration_cast<std::chrono::milliseconds>( duration ).count(), "ms" );
            m_chrono = decltype(m_chrono){};
        }
    }
}

void Parser::done( std::shared_ptr<Task> t, Status status )
{
    auto serviceIdx = t->goToNextService();

    if ( status == Status::TemporaryUnavailable ||
         status == Status::Fatal ||
         status == Status::Discarded ||
         t->isCompleted() )
    {
        ++m_opDone;

        updateStats();
        // We create a separate task for refresh, which doesn't count toward
        // (mrl,parent_playlist) uniqueness. In order to allow for a subsequent
        // refresh of the same file, we remove it once the refresh is complete.
        // In case the status was `Discarded`, the task was already deleted from
        // the database.
        if ( t->isRefresh() == true )
            Task::destroy( m_ml, t->id() );
        return;
    }
    if ( status == Status::Requeue )
    {
        // The retry_count is mostly handled when fetching the remaining tasks
        // from the database. However, when requeuing, it all happens at runtime
        // in the C++ code, so we also need to ensure we're not requeuing tasks
        // forever.
        if ( t->retryCount() > parser::MaxNbRetries )
        {
            ++m_opDone;
            updateStats();
            return;
        }
        t->resetCurrentService();
        serviceIdx = 0;
    }

    // If some services declined to parse the file, start over again.
    assert( serviceIdx < m_serviceWorkers.size() );
    updateStats();
    m_serviceWorkers[serviceIdx]->parse( std::move( t ) );
}

void Parser::onIdleChanged( bool idle )
{
    // If any parser service is not idle, then the global parser state is active
    if ( idle == false )
    {
        m_ml->onParserIdleChanged( false );
        return;
    }
    // Otherwise the parser is idle when all services are idle
    for ( const auto& s : m_serviceWorkers )
    {
        // We're switching a service from "not idle" to "idle" here, so as far as the medialibrary
        // is concerned the parser is still "not idle". In case a single parser service isn't
        // idle, no need to trigger a change to the medialibrary.
        if ( s->isIdle() == false )
            return;
    }
    m_ml->onParserIdleChanged( true );
}

}
}
<|endoftext|>


<commit_before>#include "qt/pivx/txrow.h"
#include "qt/pivx/forms/ui_txrow.h"

#include "guiutil.h"
#include <iostream>

TxRow::TxRow(bool isLightTheme, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TxRow)
{
    ui->setupUi(this);
    setConfirmStatus(true);
    updateStatus(isLightTheme, false, false);
}

void TxRow::setConfirmStatus(bool isConfirm){
    if(isConfirm){
        ui->lblAddress->setProperty("cssClass", "text-list-body1");
        ui->lblDate->setProperty("cssClass", "text-list-caption");
    }else{
        ui->lblAddress->setProperty("cssClass", "text-list-body-unconfirmed");
        ui->lblDate->setProperty("cssClass","text-list-caption-unconfirmed");
    }
}

void TxRow::updateStatus(bool isLightTheme, bool isHover, bool isSelected){
    if(isLightTheme)
        ui->lblDivisory->setStyleSheet("background-color:#bababa");
    else
        ui->lblDivisory->setStyleSheet("background-color:#40ffffff");
}

void TxRow::setDate(QDateTime date){
    ui->lblDate->setText(GUIUtil::dateTimeStr(date));
}

void TxRow::setLabel(QString str){
    ui->lblAddress->setText(str);
}

void TxRow::setAmount(QString str){
    ui->lblAmount->setText(str);
}

// TODO: Agregar send to zPIV and receive zPIV icons..
void TxRow::setType(bool isLightTheme, int type, bool isConfirmed){
    QString path;
    QString css;
    switch (type) {
        case TransactionRecord::ZerocoinMint:
            path = "://ic-transaction-mint";
            css = "text-list-amount-send";
            break;
        case TransactionRecord::Generated:
        case TransactionRecord::StakeZPIV:
        case TransactionRecord::MNReward:
        case TransactionRecord::StakeMint:
            path = "://ic-transaction-staked";
            css = "text-list-amount-receive";
            break;
        case TransactionRecord::RecvWithObfuscation:
        case TransactionRecord::RecvWithAddress:
        case TransactionRecord::RecvFromOther:
        case TransactionRecord::RecvFromZerocoinSpend:
            path = "://ic-transaction-received";
            css = "text-list-amount-receive";
            break;
        case TransactionRecord::SendToAddress:
        case TransactionRecord::SendToOther:
        case TransactionRecord::ZerocoinSpend:
        case TransactionRecord::ZerocoinSpend_Change_zPiv:
        case TransactionRecord::ZerocoinSpend_FromMe:
            path = "://ic-transaction-sent";
            css = "text-list-amount-send";
            break;
        case TransactionRecord::SendToSelf:
            path = "://ic-transaction-mint";
            css = "text-list-amount-send";
            break;
        default:
            path = ":/icons/tx_inout";
            break;
    }
    if (!isConfirmed){
        css = "text-list-amount-unconfirmed";
        path += "-inactive";
        setConfirmStatus(false);
    }else{
        setConfirmStatus(true);
    }

    if (!isLightTheme){
        path += "-dark";
    }
    ui->lblAmount->setProperty("cssClass", css);
    ui->icon->setIcon(QIcon(path));
}

TxRow::~TxRow()
{
    delete ui;
}

void TxRow::sendRow(bool isLightTheme){
    ui->lblAddress->setText("Sent to DN6i46dytMPV..hV1FuQBh7BZZ6nN");
    ui->lblDate->setText("10/04/2019");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-sent" : "://ic-transaction-sent-dark");
    ui->lblAmount->setText("-5.00 PIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-send");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}

void TxRow::receiveRow(bool isLightTheme){
    ui->lblAddress->setText("Received from DN6i46dytMPVhVBh7BZZD23");
    ui->lblDate->setText("10/04/2019");
    ui->lblAmount->setText("+0.00543 PIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-receive");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-received" : "://ic-transaction-received-dark");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}
void TxRow::stakeRow(bool isLightTheme){
    ui->lblAddress->setText("PIV Staked");
    ui->lblDate->setText("10/04/2019");
    ui->lblAmount->setText("+2.00 PIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-send");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-staked" : "://ic-transaction-staked-dark");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}
void TxRow::zPIVStakeRow(bool isLightTheme){
    ui->lblAddress->setText("zPIV Staked");
    ui->lblDate->setText("10/04/2019");
    ui->lblAmount->setText("+3.00 zPIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-send");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-staked" : "://ic-transaction-staked-dark");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}
void TxRow::mintRow(bool isLightTheme){
    ui->lblAddress->setText("Mint");
    ui->lblDate->setText("10/04/2019");
    ui->lblAmount->setText("+0.00 PIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-send");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-mint" : "://ic-transaction-mint-dark");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}
<commit_msg>[GUI] dark theme invalid icons name fix.<commit_after>#include "qt/pivx/txrow.h"
#include "qt/pivx/forms/ui_txrow.h"

#include "guiutil.h"
#include <iostream>

TxRow::TxRow(bool isLightTheme, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TxRow)
{
    ui->setupUi(this);
    setConfirmStatus(true);
    updateStatus(isLightTheme, false, false);
}

void TxRow::setConfirmStatus(bool isConfirm){
    if(isConfirm){
        ui->lblAddress->setProperty("cssClass", "text-list-body1");
        ui->lblDate->setProperty("cssClass", "text-list-caption");
    }else{
        ui->lblAddress->setProperty("cssClass", "text-list-body-unconfirmed");
        ui->lblDate->setProperty("cssClass","text-list-caption-unconfirmed");
    }
}

void TxRow::updateStatus(bool isLightTheme, bool isHover, bool isSelected){
    if(isLightTheme)
        ui->lblDivisory->setStyleSheet("background-color:#bababa");
    else
        ui->lblDivisory->setStyleSheet("background-color:#40ffffff");
}

void TxRow::setDate(QDateTime date){
    ui->lblDate->setText(GUIUtil::dateTimeStr(date));
}

void TxRow::setLabel(QString str){
    ui->lblAddress->setText(str);
}

void TxRow::setAmount(QString str){
    ui->lblAmount->setText(str);
}

// TODO: Agregar send to zPIV and receive zPIV icons..
void TxRow::setType(bool isLightTheme, int type, bool isConfirmed){
    QString path;
    QString css;
    switch (type) {
        case TransactionRecord::ZerocoinMint:
            path = "://ic-transaction-mint";
            css = "text-list-amount-send";
            break;
        case TransactionRecord::Generated:
        case TransactionRecord::StakeZPIV:
        case TransactionRecord::MNReward:
        case TransactionRecord::StakeMint:
            path = "://ic-transaction-staked";
            css = "text-list-amount-receive";
            break;
        case TransactionRecord::RecvWithObfuscation:
        case TransactionRecord::RecvWithAddress:
        case TransactionRecord::RecvFromOther:
        case TransactionRecord::RecvFromZerocoinSpend:
            path = "://ic-transaction-received";
            css = "text-list-amount-receive";
            break;
        case TransactionRecord::SendToAddress:
        case TransactionRecord::SendToOther:
        case TransactionRecord::ZerocoinSpend:
        case TransactionRecord::ZerocoinSpend_Change_zPiv:
        case TransactionRecord::ZerocoinSpend_FromMe:
            path = "://ic-transaction-sent";
            css = "text-list-amount-send";
            break;
        case TransactionRecord::SendToSelf:
            path = "://ic-transaction-mint";
            css = "text-list-amount-send";
            break;
        default:
            path = ":/icons/tx_inout";
            break;
    }

    if (!isLightTheme){
        path += "-dark";
    }

    if (!isConfirmed){
        css = "text-list-amount-unconfirmed";
        path += "-inactive";
        setConfirmStatus(false);
    }else{
        setConfirmStatus(true);
    }
    ui->lblAmount->setProperty("cssClass", css);
    ui->icon->setIcon(QIcon(path));
}

TxRow::~TxRow()
{
    delete ui;
}

void TxRow::sendRow(bool isLightTheme){
    ui->lblAddress->setText("Sent to DN6i46dytMPV..hV1FuQBh7BZZ6nN");
    ui->lblDate->setText("10/04/2019");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-sent" : "://ic-transaction-sent-dark");
    ui->lblAmount->setText("-5.00 PIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-send");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}

void TxRow::receiveRow(bool isLightTheme){
    ui->lblAddress->setText("Received from DN6i46dytMPVhVBh7BZZD23");
    ui->lblDate->setText("10/04/2019");
    ui->lblAmount->setText("+0.00543 PIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-receive");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-received" : "://ic-transaction-received-dark");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}
void TxRow::stakeRow(bool isLightTheme){
    ui->lblAddress->setText("PIV Staked");
    ui->lblDate->setText("10/04/2019");
    ui->lblAmount->setText("+2.00 PIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-send");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-staked" : "://ic-transaction-staked-dark");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}
void TxRow::zPIVStakeRow(bool isLightTheme){
    ui->lblAddress->setText("zPIV Staked");
    ui->lblDate->setText("10/04/2019");
    ui->lblAmount->setText("+3.00 zPIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-send");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-staked" : "://ic-transaction-staked-dark");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}
void TxRow::mintRow(bool isLightTheme){
    ui->lblAddress->setText("Mint");
    ui->lblDate->setText("10/04/2019");
    ui->lblAmount->setText("+0.00 PIV");
    ui->lblAmount->setProperty("cssClass", "text-list-amount-send");
    QPixmap pixmap(isLightTheme ? "://ic-transaction-mint" : "://ic-transaction-mint-dark");
    QIcon buttonIcon(pixmap);
    ui->icon->setIcon(buttonIcon);
}
<|endoftext|>


<commit_before><commit_msg>Solution for ElectrumX<commit_after><|endoftext|>


<commit_before>#ifndef COMPONENT_HPP
#define COMPONENT_HPP

#include "../MessageSystem/Observable.hpp"

#include <string>

namespace swift
{
	class Component : public Observable
	{
		public:
			static std::string getType();
	};
}

#endif // COMPONENT_HPP
<commit_msg>Made destructor default and virtual<commit_after>#ifndef COMPONENT_HPP
#define COMPONENT_HPP

#include "../MessageSystem/Observable.hpp"

#include <string>

namespace swift
{
	class Component : public Observable
	{
		public:
			virtual ~Component() = default;

			static std::string getType();
	};
}

#endif // COMPONENT_HPP
<|endoftext|>


<commit_before>#include "script/Script.h"

#define XP_UNIX
#include "jsapi.h"
#undef XP_UNIX

#include "log.h"

static JSRuntime* rt = NULL;
static JSClass scriptClassGlobal = {
    "global", JSCLASS_GLOBAL_FLAGS,
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
    JSCLASS_NO_OPTIONAL_MEMBERS
};

static void scriptReportError (JSContext* _ctx, const char* message, JSErrorReport* report)
{
    LOGW("%s:%u:%s\n",
        report->filename ? report->filename : "<no filename>",
        (unsigned int) report->lineno,
        message);
}

static JSBool amity_log (JSContext* ctx, uintN argc, jsval* vp)
{
    LOGI("amity_log %i", argc);

    JSString* message;
    if (!JS_ConvertArguments(ctx, argc, JS_ARGV(ctx, vp), "S", &message)) {
        return JS_FALSE;
    }

    LOGI("amity.log() -> %s", JS_EncodeString(ctx, message));

    return JS_TRUE;
}

static JSClass scriptClassAmity = {
    "Amity", 0,
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
};
static JSFunctionSpec scriptClassAmity_staticMethods[] = {
    // JS_TN?
    JS_FS("log", amity_log, 1, 0),
    JS_FS_END
};

static void scriptInitClasses (JSContext* ctx, JSObject* global)
{
    JSObject* amity = JS_NewObject(ctx, &scriptClassAmity, NULL, global);
    JS_DefineProperty(ctx, global, "$amity", OBJECT_TO_JSVAL(amity), NULL, NULL, 0);
    JS_DefineFunctions(ctx, amity, scriptClassAmity_staticMethods);
}

Script::~Script ()
{
    if (_ctx != NULL) {
        JS_DestroyContext(_ctx);
    }
}

int Script::parse (const char* filename, const char* source)
{
    LOGI("A");
    if (rt == NULL) {
        LOGI("Creating runtime");
        rt = JS_NewRuntime(8L * 1024L * 1024L);
        if (rt == NULL) {
            return 1;
        }
    }

    LOGI("B Creating context");
    _ctx = JS_NewContext(rt, 8192);
    if (_ctx == NULL) {
        return 1;
    }

    LOGI("C setting options");
    JS_SetOptions(_ctx,
        JSOPTION_STRICT |
        JSOPTION_WERROR |
        JSOPTION_VAROBJFIX |
        JSOPTION_NO_SCRIPT_RVAL |
        JSOPTION_JIT |
        JSOPTION_METHODJIT);
    JS_SetVersion(_ctx, JSVERSION_ECMA_5);
    JS_SetErrorReporter(_ctx, scriptReportError);

    LOGI("D creating global %s", scriptClassGlobal.name);
    JSObject* global = JS_NewGlobalObject(_ctx, &scriptClassGlobal);
    if (global == NULL) {
       return 1;
    }

    LOGI("E");
    if (!JS_InitStandardClasses(_ctx, global)) {
       return 1;
    }

    JSBool success = JS_EvaluateScript(_ctx, global, source, strlen(source),
        filename, 0, NULL);

    return !success;
}

void Script::onEnterFrame (float dt)
{
    // TODO: Call into js
}
<commit_msg>Disable some noisy logs, and create the $amity object.<commit_after>#include "script/Script.h"

#define XP_UNIX
#include "jsapi.h"
#undef XP_UNIX

#include "log.h"

static JSRuntime* rt = NULL;
static JSClass scriptClassGlobal = {
    "global", JSCLASS_GLOBAL_FLAGS,
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
    JSCLASS_NO_OPTIONAL_MEMBERS
};

static void scriptReportError (JSContext* _ctx, const char* message, JSErrorReport* report)
{
    LOGW("%s:%u:%s\n",
        report->filename ? report->filename : "<no filename>",
        (unsigned int) report->lineno,
        message);
}

static JSBool amity_log (JSContext* ctx, uintN argc, jsval* vp)
{
    JSString* message;
    if (!JS_ConvertArguments(ctx, argc, JS_ARGV(ctx, vp), "S", &message)) {
        return JS_FALSE;
    }

    LOGI("amity.log() -> %s", JS_EncodeString(ctx, message));

    return JS_TRUE;
}

static JSClass scriptClassAmity = {
    "Amity", 0,
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
};
static JSFunctionSpec scriptClassAmity_staticMethods[] = {
    // JS_TN?
    JS_FS("log", amity_log, 1, 0),
    JS_FS_END
};

static void scriptInitClasses (JSContext* ctx, JSObject* global)
{
    JSObject* amity = JS_NewObject(ctx, &scriptClassAmity, NULL, global);
    JS_DefineProperty(ctx, global, "$amity", OBJECT_TO_JSVAL(amity), NULL, NULL, 0);
    JS_DefineFunctions(ctx, amity, scriptClassAmity_staticMethods);
}

Script::~Script ()
{
    if (_ctx != NULL) {
        JS_DestroyContext(_ctx);
    }
}

int Script::parse (const char* filename, const char* source)
{
    if (rt == NULL) {
        LOGI("Creating runtime");
        rt = JS_NewRuntime(8L * 1024L * 1024L);
        if (rt == NULL) {
            return 1;
        }
    }

    _ctx = JS_NewContext(rt, 8192);
    if (_ctx == NULL) {
        return 1;
    }

    JS_SetOptions(_ctx,
        JSOPTION_STRICT |
        JSOPTION_WERROR |
        JSOPTION_VAROBJFIX |
        JSOPTION_NO_SCRIPT_RVAL |
        JSOPTION_JIT |
        JSOPTION_METHODJIT);
    JS_SetVersion(_ctx, JSVERSION_ECMA_5);
    JS_SetErrorReporter(_ctx, scriptReportError);

    JSObject* global = JS_NewGlobalObject(_ctx, &scriptClassGlobal);
    if (global == NULL) {
       return 1;
    }

    if (!JS_InitStandardClasses(_ctx, global)) {
       return 1;
    }
    scriptInitClasses(_ctx, global);

    JSBool success = JS_EvaluateScript(_ctx, global, source, strlen(source),
        filename, 0, NULL);

    return !success;
}

void Script::onEnterFrame (float dt)
{
    // TODO: Call into js
}
<|endoftext|>


<commit_before>// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

/**
 * File:   BarPeriod.cpp
 * Author: kan
 *
 * Created on 11.11.2015.
 */

#include <cmath>
#include <time.h>
#include <stddef.h>
#include <cassert>
#include <sstream>

#include "Comparers.h"
#include "DelphisRound.h"
#include "BarPeriod.h"

#include "BasisOfStrategy.h"

//------------------------------------------------------------------------------------------
const std::string whitespaces (" \t\f\v\n\r");
std::string trim( const std::string& str ) {
    const size_t first = str.find_first_not_of( whitespaces );
    if( std::string::npos == first ) {
        return str;
    }
    const size_t last = str.find_last_not_of( whitespaces );
    return str.substr(first, (last - first + 1));
}

//------------------------------------------------------------------------------------------
bool IsOneDay( const TInnerDate aLeft, const TInnerDate aRight) {
    return Trunc( aLeft / gOneDay ) == Trunc( aRight / gOneDay );
}

//------------------------------------------------------------------------------------------
bool IsOneHour( const TInnerDate aLeft, const TInnerDate aRight, const double aDuration ) {
    assert( isPositiveValue( aDuration ) );
    return IsLess( std::fabs( aLeft - aRight ), gOneHour*aDuration + 1.0 );
}

//------------------------------------------------------------------------------------------
bool IsValidBar( const TSimpleBar & aBar ) {
    return IsGreat( aBar.Volume, -2.0 * gAbsoluteZero ) // >= 0
           and IsValidPrice( aBar.Open )
           and IsValidPrice( aBar.High )
           and IsValidPrice( aBar.Low )
           and IsValidPrice( aBar.Close );
}

//------------------------------------------------------------------------------------------
#define FAST_DECODER( aField ) \
    for( std::size_t lRowNum = 0; lRowNum < aBar.size(); ++lRowNum ) { \
        TSimpleBar lBar = aBar[ lRowNum ]; \
        TPrice lPrice = lBar.aField; \
        TSimpleTick lTick { lBar.DateTime, lPrice, lBar.Volume }; \
        lResult[ lRowNum ] = lTick; \
    } \
// end of FAST_DECODER

TPriceSeries BarsToPriceSeries( const TBarSeries &aBar, const TMAPoint aType ) {

    TPriceSeries lResult( aBar.size() );

    switch ( aType ) {
        /////////
        case TMAPoint::MAP_Close : {
            FAST_DECODER( Close );
        } break ;
        /////////
        case TMAPoint::MAP_Mid : {
            for( std::size_t lRowNum = 0; lRowNum < aBar.size(); ++lRowNum ) {
                TSimpleBar lBar = aBar[ lRowNum ];
                TPrice lPrice = ( lBar.High + lBar.Low ) / 2.0 ;
                TSimpleTick lTick { lBar.DateTime, lPrice, lBar.Volume };
                lResult[ lRowNum ] = lTick;
            }
        } break ;
        /////////
        case TMAPoint::MAP_Triple : {
            for( std::size_t lRowNum = 0; lRowNum < aBar.size(); ++lRowNum ) {
                TSimpleBar lBar = aBar[ lRowNum ];
                TPrice lPrice = ( lBar.High + lBar.Low + lBar.Close ) / 3.0 ;
                TSimpleTick lTick { lBar.DateTime, lPrice, lBar.Volume };
                lResult[ lRowNum ] = lTick;
            }
        } break ;
        /////////
        case TMAPoint::MAP_Open : {
            FAST_DECODER( Open );
        } break ;
        /////////
        case TMAPoint::MAP_High : {
            FAST_DECODER( High );
        } break ;
        /////////
        case TMAPoint::MAP_Low : {
            FAST_DECODER( Low );
        } break ;
        /////////
        case TMAPoint::MAP_Volume : {
            FAST_DECODER( Volume );
        } break ;
    }

    return lResult;
}

//------------------------------------------------------------------------------------------
void Reset( TSimpleBar &aBar ) {
    aBar.DateTime = gStartingTime;
    aBar.Open = 0.0;
    aBar.High = 0.0;
    aBar.Low = 0.0;
    aBar.Close = 0.0;
    aBar.Volume = -1.0;
}

//------------------------------------------------------------------------------------------
TBarSeries _CreateBars( const TBarSeries & aBars, const TBarPeriod aBarPeriod ) {

    const double lOutBarPeriod = getBarPeriodLength( aBarPeriod );//0.0;

    TBarSeries oResuiltBarSeries;
    TSimpleBar lOutBar;
    Reset( lOutBar );

    int GlobalBarIndex = 0;

    for( size_t i = 0; i < aBars.size( ); i++ ) {

        const TSimpleBar lCurrentBar = aBars[ i ];
        const TInnerDate lBarTime = lCurrentBar.DateTime;
        const int lCurrentBarIndex = Trunc( ( lBarTime - gStartingTime ) / lOutBarPeriod );

        if( lCurrentBarIndex != GlobalBarIndex ) {

            if( GlobalBarIndex != 0 ) {
                lOutBar.DateTime = GlobalBarIndex * lOutBarPeriod + gStartingTime;
                oResuiltBarSeries.push_back( lOutBar );
                Reset( lOutBar );
            }

            GlobalBarIndex = lCurrentBarIndex;
        }

        lOutBar = lOutBar + lCurrentBar;

        if( ( aBars.size( ) - i ) == 1 ) {
            lOutBar.DateTime = lCurrentBarIndex * lOutBarPeriod + gStartingTime;
            oResuiltBarSeries.push_back( lOutBar );
            Reset( lOutBar );
        }
    }

    return oResuiltBarSeries;
}

//------------------------------------------------------------------------------------------
TSimpleBar operator+( const TSimpleBar &aStarBar, const TSimpleBar &aEndBar ) {

    if( not IsValidBar( aEndBar ) ) {
        return aStarBar;
    }

    if( not IsValidBar( aStarBar ) ) {
        return aEndBar;
    }

    const double lOpen =  aStarBar.Open;
    const double lHigh = IsGreat( aStarBar.High, aEndBar.High ) ? aStarBar.High : aEndBar.High ;
    const double lLow = IsLess( aStarBar.Low, aEndBar.Low ) ? aStarBar.Low : aEndBar.Low;
    const double lClose = aEndBar.Close;
    const double lVolume = aStarBar.Volume + aEndBar.Volume;

    const TSimpleBar lOutBar{ aStarBar.DateTime, lOpen, lHigh, lLow, lClose, lVolume };

    return lOutBar;
}

//------------------------------------------------------------------------------------------
std::string DateToStr( const TInnerDate aDate ) {
    const time_t lTime = Round( aDate );
    const std::string lStrTime( ctime( &lTime ) );

    return trim( lStrTime );
}

//------------------------------------------------------------------------------------------
TInnerTime ITime( const TInnerDate aDate ) {
    // const time_t lTime = Round( aDate );
    // struct tm * ltimeinfo = localtime (&lTime);

    // return ltimeinfo->tm_hour * 3600 + ltimeinfo->tm_min * 60 + ltimeinfo->tm_sec;
    return  ToDouble(ToInt(aDate) % ToInt(gOneDay));
}

//------------------------------------------------------------------------------------------
TInnerTime ITime( const std::string& aTime ) {
    std::string s{aTime};
    const std::string delimiter{":"};
    int lHours;
    size_t pos = 0;

    if ((pos = s.find(delimiter)) != std::string::npos) {
        lHours = std::stoi(s.substr(0, pos));
        s.erase(0, pos + delimiter.length());
    } else {
        return 0.0;
    }

    if ((pos = s.find(delimiter)) != std::string::npos) {
        int lMinutes = std::stoi(s.substr(0, pos));
        s.erase(0, pos + delimiter.length());
        int lSeconds = std::stoi(s.substr(0, pos));

        return ToDouble(lHours * 3600 + lMinutes * 60 + lSeconds);
    } else {
        int lMinutes = std::stoi(s);
        return ToDouble(lHours * 3600 + lMinutes * 60);
    }
}

//------------------------------------------------------------------------------------------
std::ostream& operator<<( std::ostream &out, const TSimpleBar &aBar ) {
    std::stringstream strm;

    strm    << DateToStr( aBar.DateTime ) << "\t"
            << aBar.Open << "\t"
            << aBar.High << "\t"
            << aBar.Low << "\t"
            << aBar.Close << "\t"
            << aBar.Volume ;

    return out << strm.str();
}

//------------------------------------------------------------------------------------------
std::ostream& operator<<( std::ostream &out, const TSimpleTick &aTick ) {
    std::stringstream strm;

    strm    << DateToStr( aTick.DateTime ) << "\t"
            << aTick.Price << "\t"
            << aTick.Volume ;
    return out << strm.str();
}

//------------------------------------------------------------------------------------------
TPrice RoundTo( const TPrice aPrice, const TPrice aPriceStep ) {
    assert( isPositiveValue( aPriceStep ) );

    return std::round( aPrice / aPriceStep ) * aPriceStep ;
}

//------------------------------------------------------------------------------------------
TPrice TruncTo( const TPrice aPrice, const TPrice aPriceStep ) {
    assert( isPositiveValue( aPriceStep ) );

    return std::trunc( aPrice / aPriceStep ) * aPriceStep ;
}

//------------------------------------------------------------------------------------------
TPrice CeilTo( const TPrice aPrice, const TPrice aPriceStep ) {
    assert( isPositiveValue( aPriceStep ) );

    return std::ceil( aPrice / aPriceStep ) * aPriceStep ;
}

//------------------------------------------------------------------------------------------
<commit_msg>[*] IsOneHour<commit_after>// This is an independent project of an individual developer. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

/**
 * File:   BarPeriod.cpp
 * Author: kan
 *
 * Created on 11.11.2015.
 */

#include <cmath>
#include <time.h>
#include <stddef.h>
#include <cassert>
#include <sstream>

#include "Comparers.h"
#include "DelphisRound.h"
#include "BarPeriod.h"

#include "BasisOfStrategy.h"

//------------------------------------------------------------------------------------------
const std::string whitespaces (" \t\f\v\n\r");
std::string trim( const std::string& str ) {
    const size_t first = str.find_first_not_of( whitespaces );
    if( std::string::npos == first ) {
        return str;
    }
    const size_t last = str.find_last_not_of( whitespaces );
    return str.substr(first, (last - first + 1));
}

//------------------------------------------------------------------------------------------
bool IsOneDay( const TInnerDate aLeft, const TInnerDate aRight) {
    return Trunc( aLeft / gOneDay ) == Trunc( aRight / gOneDay );
}

//------------------------------------------------------------------------------------------
bool IsOneHour( const TInnerDate aLeft, const TInnerDate aRight, const double aDuration ) {
    assert( isPositiveValue( aDuration ) );
    //return IsLess( std::fabs( aLeft - aRight ), gOneHour*aDuration + 1.0 );

    return Trunc( aLeft / (gOneHour*aDuration) ) == Trunc( aRight / (gOneHour*aDuration) );
}

//------------------------------------------------------------------------------------------
bool IsValidBar( const TSimpleBar & aBar ) {
    return IsGreat( aBar.Volume, -2.0 * gAbsoluteZero ) // >= 0
           and IsValidPrice( aBar.Open )
           and IsValidPrice( aBar.High )
           and IsValidPrice( aBar.Low )
           and IsValidPrice( aBar.Close );
}

//------------------------------------------------------------------------------------------
#define FAST_DECODER( aField ) \
    for( std::size_t lRowNum = 0; lRowNum < aBar.size(); ++lRowNum ) { \
        TSimpleBar lBar = aBar[ lRowNum ]; \
        TPrice lPrice = lBar.aField; \
        TSimpleTick lTick { lBar.DateTime, lPrice, lBar.Volume }; \
        lResult[ lRowNum ] = lTick; \
    } \
// end of FAST_DECODER

TPriceSeries BarsToPriceSeries( const TBarSeries &aBar, const TMAPoint aType ) {

    TPriceSeries lResult( aBar.size() );

    switch ( aType ) {
        /////////
        case TMAPoint::MAP_Close : {
            FAST_DECODER( Close );
        } break ;
        /////////
        case TMAPoint::MAP_Mid : {
            for( std::size_t lRowNum = 0; lRowNum < aBar.size(); ++lRowNum ) {
                TSimpleBar lBar = aBar[ lRowNum ];
                TPrice lPrice = ( lBar.High + lBar.Low ) / 2.0 ;
                TSimpleTick lTick { lBar.DateTime, lPrice, lBar.Volume };
                lResult[ lRowNum ] = lTick;
            }
        } break ;
        /////////
        case TMAPoint::MAP_Triple : {
            for( std::size_t lRowNum = 0; lRowNum < aBar.size(); ++lRowNum ) {
                TSimpleBar lBar = aBar[ lRowNum ];
                TPrice lPrice = ( lBar.High + lBar.Low + lBar.Close ) / 3.0 ;
                TSimpleTick lTick { lBar.DateTime, lPrice, lBar.Volume };
                lResult[ lRowNum ] = lTick;
            }
        } break ;
        /////////
        case TMAPoint::MAP_Open : {
            FAST_DECODER( Open );
        } break ;
        /////////
        case TMAPoint::MAP_High : {
            FAST_DECODER( High );
        } break ;
        /////////
        case TMAPoint::MAP_Low : {
            FAST_DECODER( Low );
        } break ;
        /////////
        case TMAPoint::MAP_Volume : {
            FAST_DECODER( Volume );
        } break ;
    }

    return lResult;
}

//------------------------------------------------------------------------------------------
void Reset( TSimpleBar &aBar ) {
    aBar.DateTime = gStartingTime;
    aBar.Open = 0.0;
    aBar.High = 0.0;
    aBar.Low = 0.0;
    aBar.Close = 0.0;
    aBar.Volume = -1.0;
}

//------------------------------------------------------------------------------------------
TBarSeries _CreateBars( const TBarSeries & aBars, const TBarPeriod aBarPeriod ) {

    const double lOutBarPeriod = getBarPeriodLength( aBarPeriod );//0.0;

    TBarSeries oResuiltBarSeries;
    TSimpleBar lOutBar;
    Reset( lOutBar );

    int GlobalBarIndex = 0;

    for( size_t i = 0; i < aBars.size( ); i++ ) {

        const TSimpleBar lCurrentBar = aBars[ i ];
        const TInnerDate lBarTime = lCurrentBar.DateTime;
        const int lCurrentBarIndex = Trunc( ( lBarTime - gStartingTime ) / lOutBarPeriod );

        if( lCurrentBarIndex != GlobalBarIndex ) {

            if( GlobalBarIndex != 0 ) {
                lOutBar.DateTime = GlobalBarIndex * lOutBarPeriod + gStartingTime;
                oResuiltBarSeries.push_back( lOutBar );
                Reset( lOutBar );
            }

            GlobalBarIndex = lCurrentBarIndex;
        }

        lOutBar = lOutBar + lCurrentBar;

        if( ( aBars.size( ) - i ) == 1 ) {
            lOutBar.DateTime = lCurrentBarIndex * lOutBarPeriod + gStartingTime;
            oResuiltBarSeries.push_back( lOutBar );
            Reset( lOutBar );
        }
    }

    return oResuiltBarSeries;
}

//------------------------------------------------------------------------------------------
TSimpleBar operator+( const TSimpleBar &aStarBar, const TSimpleBar &aEndBar ) {

    if( not IsValidBar( aEndBar ) ) {
        return aStarBar;
    }

    if( not IsValidBar( aStarBar ) ) {
        return aEndBar;
    }

    const double lOpen =  aStarBar.Open;
    const double lHigh = IsGreat( aStarBar.High, aEndBar.High ) ? aStarBar.High : aEndBar.High ;
    const double lLow = IsLess( aStarBar.Low, aEndBar.Low ) ? aStarBar.Low : aEndBar.Low;
    const double lClose = aEndBar.Close;
    const double lVolume = aStarBar.Volume + aEndBar.Volume;

    const TSimpleBar lOutBar{ aStarBar.DateTime, lOpen, lHigh, lLow, lClose, lVolume };

    return lOutBar;
}

//------------------------------------------------------------------------------------------
std::string DateToStr( const TInnerDate aDate ) {
    const time_t lTime = Round( aDate );
    const std::string lStrTime( ctime( &lTime ) );

    return trim( lStrTime );
}

//------------------------------------------------------------------------------------------
TInnerTime ITime( const TInnerDate aDate ) {
    // const time_t lTime = Round( aDate );
    // struct tm * ltimeinfo = localtime (&lTime);

    // return ltimeinfo->tm_hour * 3600 + ltimeinfo->tm_min * 60 + ltimeinfo->tm_sec;
    return  ToDouble(ToInt(aDate) % ToInt(gOneDay));
}

//------------------------------------------------------------------------------------------
TInnerTime ITime( const std::string& aTime ) {
    std::string s{aTime};
    const std::string delimiter{":"};
    int lHours;
    size_t pos = 0;

    if ((pos = s.find(delimiter)) != std::string::npos) {
        lHours = std::stoi(s.substr(0, pos));
        s.erase(0, pos + delimiter.length());
    } else {
        return 0.0;
    }

    if ((pos = s.find(delimiter)) != std::string::npos) {
        int lMinutes = std::stoi(s.substr(0, pos));
        s.erase(0, pos + delimiter.length());
        int lSeconds = std::stoi(s.substr(0, pos));

        return ToDouble(lHours * 3600 + lMinutes * 60 + lSeconds);
    } else {
        int lMinutes = std::stoi(s);
        return ToDouble(lHours * 3600 + lMinutes * 60);
    }
}

//------------------------------------------------------------------------------------------
std::ostream& operator<<( std::ostream &out, const TSimpleBar &aBar ) {
    std::stringstream strm;

    strm    << DateToStr( aBar.DateTime ) << "\t"
            << aBar.Open << "\t"
            << aBar.High << "\t"
            << aBar.Low << "\t"
            << aBar.Close << "\t"
            << aBar.Volume ;

    return out << strm.str();
}

//------------------------------------------------------------------------------------------
std::ostream& operator<<( std::ostream &out, const TSimpleTick &aTick ) {
    std::stringstream strm;

    strm    << DateToStr( aTick.DateTime ) << "\t"
            << aTick.Price << "\t"
            << aTick.Volume ;
    return out << strm.str();
}

//------------------------------------------------------------------------------------------
TPrice RoundTo( const TPrice aPrice, const TPrice aPriceStep ) {
    assert( isPositiveValue( aPriceStep ) );

    return std::round( aPrice / aPriceStep ) * aPriceStep ;
}

//------------------------------------------------------------------------------------------
TPrice TruncTo( const TPrice aPrice, const TPrice aPriceStep ) {
    assert( isPositiveValue( aPriceStep ) );

    return std::trunc( aPrice / aPriceStep ) * aPriceStep ;
}

//------------------------------------------------------------------------------------------
TPrice CeilTo( const TPrice aPrice, const TPrice aPriceStep ) {
    assert( isPositiveValue( aPriceStep ) );

    return std::ceil( aPrice / aPriceStep ) * aPriceStep ;
}

//------------------------------------------------------------------------------------------
<|endoftext|>


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

#include <vector>
#include <iostream>
#include <exception>
#include <iomanip>
#include <ctime>
#include <algorithm>

#include <configuration.hpp>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Correlator.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

const unsigned int magicValue = 42;

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, cl::Buffer * output_d);

int main(int argc, char * argv[]) {
  bool reInit = true;
  unsigned int padding = 0;
  unsigned int nrIterations = 0;
  unsigned int clPlatformID = 0;
  unsigned int clDeviceID = 0;
  unsigned int vectorSize = 0;
  unsigned int maxThreads = 0;
  unsigned int maxItems = 0;
  unsigned int nrChannels = 0;
  unsigned int nrStations = 0;
  unsigned int nrSamples = 0;
  isa::OpenCL::KernelConf conf;

  try {
    isa::utils::ArgumentList args(argc, argv);

    clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
    clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
    vectorSize = args.getSwitchArgument< unsigned int >("-vector");
    maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
    maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    nrChannels = args.getSwitchArgument< unsigned int >("-channels");
    nrStations = args.getSwitchArgument< unsigned int >("-stations");
    nrSamples = args.getSwitchArgument< unsigned int >("-samples");
  } catch ( isa::utils::EmptyCommandLine & err ) {
    std::cerr << argv[0] << " -opencl_platform ... -opencl_device ... -padding ... -iterations ... -vector ... -max_threads ... -max_items ... -channels ... -stations ... -samples ..." << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  cl::Context clContext;
  std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
  std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
  std::vector< std::vector< cl::CommandQueue > > * clQueues = 0;

  // Allocate host memory
  unsigned int nrBaselines = (nrStations * (nrStations + 1)) / 2;
  std::vector< inputDataType > input(nrChannels * nrStations * nrSamples * nrPolarizations * 2), output(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2), output_c(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2);
  cl::Buffer input_d, output_d;

  // Populate data structures
  srand(time(0));
  for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
    for ( unsigned int station = 0; station < nrStations; station++ ) {
      for ( unsigned int sample = 0; sample < nrSamples; sample++ ) {
        for ( unsigned int polarization = 0; polarization < nrPolarizations; polarization++ ) {
          input[(channel * nrStations * nrSamples * nrPolarizations * 2) + (station * nrSamples * nrPolarizations * 2) + (sample * nrPolarizations * 2) + (polarization * 2)] = rand() % magicValue;
          input[(channel * nrStations * nrSamples * nrPolarizations * 2) + (station * nrSamples * nrPolarizations * 2) + (sample * nrPolarizations * 2) + (polarization * 2) + 1] = rand() % magicValue;
        }
      }
    }
  }
  // Compute CPU control results
  std::fill(output.begin(), output.end(), 0);
  TuneBench::correlator(input, output_c, nrChannels, nrStations, nrSamples, nrPolarizations);

  std::cout << std::fixed << std::endl;
  std::cout << "# nrChannels nrStations nrSamples nrPolarizations nrThreadsD0 nrItemsD0 nrItemsD1 GFLOP/s time stdDeviation COV" << std::endl << std::endl;

  for ( unsigned int threads = vectorSize; threads <= maxThreads; threads += vectorSize ) {
    conf.setNrThreadsD0(threads);
    for ( unsigned int items = 1; items <= maxItems; items++ ) {
      conf.setNrItemsD0(items);
      if ( nrSamples % (conf.getNrThreadsD0() * conf.getNrItemsD0()) != 0 ) {
        continue;
      }
      for ( unsigned int items = 1; (1 + (5 * conf.getNrItemsD1()) + (8 * ((conf.getNrItemsD1() * (conf.getNrItemsD1() + 1)) / 2))) <= maxItems; items++ ) {
        conf.setNrItemsD1(items);
        if ( nrStations % (conf.getNrItemsD1()) != 0 ) {
          continue;
        }

        // Generate kernel
        double gflops = isa::utils::giga(static_cast< uint64_t >(nrChannels) * nrSamples * nrBaselines * 32);
        cl::Event clEvent;
        cl::Kernel * kernel;
        isa::utils::Timer timer;
        std::string * code = TuneBench::getCorrelatorOpenCL(conf, inputDataName, padding, nrChannels, nrStations, nrSamples, nrPolarizations);

        if ( reInit ) {
          delete clQueues;
          clQueues = new std::vector< std::vector< cl::CommandQueue > >();
          isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
          try {
            initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), &input, &input_d, &output_d);
          } catch ( cl::Error & err ) {
            return -1;
          }
          reInit = false;
        }
        try {
          kernel = isa::OpenCL::compile("correlator", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
        } catch ( isa::OpenCL::OpenCLError & err ) {
          std::cerr << err.what() << std::endl;
          delete code;
          break;
        }
        delete code;

        cl::NDRange global(nrSamples / conf.getNrItemsD0(), nrStations / conf.getNrItemsD1(), nrChannels);
        cl::NDRange local(conf.getNrThreadsD0(), 1, 1);

        kernel->setArg(0, input_d);
        kernel->setArg(1, output_d);

        try {
          // Warm-up run
          clQueues->at(clDeviceID)[0].finish();
          clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
          clEvent.wait();
          // Tuning runs
          for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
            timer.start();
            clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
            clEvent.wait();
            timer.stop();
          }
          clQueues->at(clDeviceID)[0].enqueueReadBuffer(output_d, CL_TRUE, 0, output.size() * sizeof(inputDataType), reinterpret_cast< void * >(output.data()), 0, &clEvent);
          clEvent.wait();
        } catch ( cl::Error & err ) {
          reInit = true;
          std::cerr << "OpenCL kernel execution error (";
          std::cerr << conf.print();
          std::cerr << "): ";
          std::cerr << isa::utils::toString(err.err()) << std::endl;
          delete kernel;
          if ( err.err() == -4 || err.err() == -61 ) {
            return -1;
          }
          break;
        }
        delete kernel;

        bool error = false;
        for ( unsigned int item = 0; item < output_c.size(); item++ ) {
          if ( !isa::utils::same(output[item], output_c[item]) ) {
            std::cerr << "Output error (" << conf.print() << ")." << std::endl;
            error = true;
            break;
          }
        }
        if ( error ) {
          continue;
        }

        std::cout << nrChannels << " " << nrStations << " " << nrSamples << " " << nrPolarizations << " " ;
        std::cout << conf.print() << " ";
        std::cout << std::setprecision(3);
        std::cout << gflops / timer.getAverageTime() << " ";
        std::cout << std::setprecision(6);
        std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " " << timer.getCoefficientOfVariation() << std::endl;
      }
    }
  }
  std::cout << std::endl;

  return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, cl::Buffer * output_d) {
  try {
    *input_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    *output_d = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    clQueue->enqueueWriteBuffer(*input_d, CL_FALSE, 0, input->size() * sizeof(inputDataType), reinterpret_cast< void * >(input->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error (memory initialization): " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

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

#include <vector>
#include <iostream>
#include <exception>
#include <iomanip>
#include <ctime>
#include <algorithm>

#include <configuration.hpp>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Correlator.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

const unsigned int magicValue = 42;

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, cl::Buffer * output_d);

int main(int argc, char * argv[]) {
  bool reInit = true;
  unsigned int padding = 0;
  unsigned int nrIterations = 0;
  unsigned int clPlatformID = 0;
  unsigned int clDeviceID = 0;
  unsigned int vectorSize = 0;
  unsigned int maxThreads = 0;
  unsigned int maxItems = 0;
  unsigned int nrChannels = 0;
  unsigned int nrStations = 0;
  unsigned int nrSamples = 0;
  isa::OpenCL::KernelConf conf;

  try {
    isa::utils::ArgumentList args(argc, argv);

    clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
    clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
    vectorSize = args.getSwitchArgument< unsigned int >("-vector");
    maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
    maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    nrChannels = args.getSwitchArgument< unsigned int >("-channels");
    nrStations = args.getSwitchArgument< unsigned int >("-stations");
    nrSamples = args.getSwitchArgument< unsigned int >("-samples");
  } catch ( isa::utils::EmptyCommandLine & err ) {
    std::cerr << argv[0] << " -opencl_platform ... -opencl_device ... -padding ... -iterations ... -vector ... -max_threads ... -max_items ... -channels ... -stations ... -samples ..." << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  cl::Context clContext;
  std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
  std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
  std::vector< std::vector< cl::CommandQueue > > * clQueues = 0;

  // Allocate host memory
  unsigned int nrBaselines = (nrStations * (nrStations + 1)) / 2;
  std::vector< inputDataType > input(nrChannels * nrStations * nrSamples * nrPolarizations * 2), output(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2), output_c(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2);
  cl::Buffer input_d, output_d;

  // Populate data structures
  srand(time(0));
  for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
    for ( unsigned int station = 0; station < nrStations; station++ ) {
      for ( unsigned int sample = 0; sample < nrSamples; sample++ ) {
        for ( unsigned int polarization = 0; polarization < nrPolarizations; polarization++ ) {
          input[(channel * nrStations * nrSamples * nrPolarizations * 2) + (station * nrSamples * nrPolarizations * 2) + (sample * nrPolarizations * 2) + (polarization * 2)] = rand() % magicValue;
          input[(channel * nrStations * nrSamples * nrPolarizations * 2) + (station * nrSamples * nrPolarizations * 2) + (sample * nrPolarizations * 2) + (polarization * 2) + 1] = rand() % magicValue;
        }
      }
    }
  }
  // Compute CPU control results
  std::fill(output.begin(), output.end(), 0);
  TuneBench::correlator(input, output_c, nrChannels, nrStations, nrSamples, nrPolarizations);

  std::cout << std::fixed << std::endl;
  std::cout << "# nrChannels nrStations nrSamples nrPolarizations nrThreadsD0 nrItemsD0 nrItemsD1 GFLOP/s time stdDeviation COV" << std::endl << std::endl;

  for ( unsigned int threads = vectorSize; threads <= maxThreads; threads += vectorSize ) {
    conf.setNrThreadsD0(threads);
    for ( unsigned int items = 1; items <= maxItems; items++ ) {
      conf.setNrItemsD0(items);
      if ( nrSamples % (conf.getNrThreadsD0() * conf.getNrItemsD0()) != 0 ) {
        continue;
      }
      for ( unsigned int items = 1; (1 + (5 * items) + (8 * ((items * (items + 1)) / 2))) <= maxItems; items++ ) {
        conf.setNrItemsD1(items);
        if ( nrStations % (conf.getNrItemsD1()) != 0 ) {
          continue;
        }

        // Generate kernel
        double gflops = isa::utils::giga(static_cast< uint64_t >(nrChannels) * nrSamples * nrBaselines * 32);
        cl::Event clEvent;
        cl::Kernel * kernel;
        isa::utils::Timer timer;
        std::string * code = TuneBench::getCorrelatorOpenCL(conf, inputDataName, padding, nrChannels, nrStations, nrSamples, nrPolarizations);

        if ( reInit ) {
          delete clQueues;
          clQueues = new std::vector< std::vector< cl::CommandQueue > >();
          isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
          try {
            initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), &input, &input_d, &output_d);
          } catch ( cl::Error & err ) {
            return -1;
          }
          reInit = false;
        }
        try {
          kernel = isa::OpenCL::compile("correlator", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
        } catch ( isa::OpenCL::OpenCLError & err ) {
          std::cerr << err.what() << std::endl;
          delete code;
          break;
        }
        delete code;

        cl::NDRange global(nrSamples / conf.getNrItemsD0(), nrStations / conf.getNrItemsD1(), nrChannels);
        cl::NDRange local(conf.getNrThreadsD0(), 1, 1);

        kernel->setArg(0, input_d);
        kernel->setArg(1, output_d);

        try {
          // Warm-up run
          clQueues->at(clDeviceID)[0].finish();
          clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
          clEvent.wait();
          // Tuning runs
          for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
            timer.start();
            clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
            clEvent.wait();
            timer.stop();
          }
          clQueues->at(clDeviceID)[0].enqueueReadBuffer(output_d, CL_TRUE, 0, output.size() * sizeof(inputDataType), reinterpret_cast< void * >(output.data()), 0, &clEvent);
          clEvent.wait();
        } catch ( cl::Error & err ) {
          reInit = true;
          std::cerr << "OpenCL kernel execution error (";
          std::cerr << conf.print();
          std::cerr << "): ";
          std::cerr << isa::utils::toString(err.err()) << std::endl;
          delete kernel;
          if ( err.err() == -4 || err.err() == -61 ) {
            return -1;
          }
          break;
        }
        delete kernel;

        bool error = false;
        for ( unsigned int item = 0; item < output_c.size(); item++ ) {
          if ( !isa::utils::same(output[item], output_c[item]) ) {
            std::cerr << "Output error (" << conf.print() << ")." << std::endl;
            error = true;
            break;
          }
        }
        if ( error ) {
          continue;
        }

        std::cout << nrChannels << " " << nrStations << " " << nrSamples << " " << nrPolarizations << " " ;
        std::cout << conf.print() << " ";
        std::cout << std::setprecision(3);
        std::cout << gflops / timer.getAverageTime() << " ";
        std::cout << std::setprecision(6);
        std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " " << timer.getCoefficientOfVariation() << std::endl;
      }
    }
  }
  std::cout << std::endl;

  return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, cl::Buffer * output_d) {
  try {
    *input_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    *output_d = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    clQueue->enqueueWriteBuffer(*input_d, CL_FALSE, 0, input->size() * sizeof(inputDataType), reinterpret_cast< void * >(input->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error (memory initialization): " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

<|endoftext|>


<commit_before>/*
 NUI3 - C++ cross-platform GUI framework for OpenGL based applications
 Copyright (C) 2002-2003 Sebastien Metrot

 licence: see nui3/LICENCE.TXT
 */

#include "nui.h"
#include "nuiDrawContext.h"
#include "nuiImageSequence.h"

nuiImageSequence::nuiImageSequence()
: nuiWidget(), mFrameIndex(0)
{
  if (SetObjectClass(_T("nuiImageSequence")))
    InitAttributes();
  mColor = nuiColor(255,255,255);
  mInterpolated = true;
  mNbFrames = 0;
  mpTempImage = NULL;
  mRefreshTextures = true;
  mUseAlpha = false;
}

nuiImageSequence::nuiImageSequence(uint32 nbFrames, nglImage* pImage, nuiOrientation orientation, const nuiColor& rColor)
: nuiWidget(), mFrameIndex(0),
mColor(rColor)
{
  if (SetObjectClass(_T("nuiImageSequence")))
    InitAttributes();
  mInterpolated = true;
  mNbFrames = nbFrames;
  mOrientation = orientation;
  mpTempImage = new nglImage(*pImage);
  mRefreshTextures = true;
  mUseAlpha = false;
}

nuiImageSequence::nuiImageSequence(uint32 nbFrames, const nglPath& rTexturePath, nuiOrientation orientation, const nuiColor& rColor)
: nuiWidget(), mFrameIndex(0),
mColor(rColor),
mGlobalTexturePath(rTexturePath)
{
  if (SetObjectClass(_T("nuiImageSequence")))
    InitAttributes();

  mpTempImage = new nglImage(rTexturePath);

  mInterpolated = true;
  mNbFrames = nbFrames;
  mOrientation = orientation;
  mRefreshTextures = true;
  mUseAlpha = false;
}

void nuiImageSequence::InitAttributes()
{
  nuiAttribute<const nuiColor&>* AttributeColor = new nuiAttribute<const nuiColor&>
  (nglString(_T("Color")), nuiUnitNone,
   nuiAttribute<const nuiColor&>::GetterDelegate(this, &nuiImageSequence::GetColor),
   nuiAttribute<const nuiColor&>::SetterDelegate(this, &nuiImageSequence::SetColor));

  nuiAttribute<const nglPath&>* AttributeTexture = new nuiAttribute<const nglPath&>
  (nglString(_T("Texture")), nuiUnitNone,
   nuiFastDelegate::MakeDelegate(this, &nuiImageSequence::GetTexturePath),
   nuiFastDelegate::MakeDelegate(this, &nuiImageSequence::SetTexturePath));

  nuiAttribute<bool>* AttributeInterpolation = new nuiAttribute<bool>
  (nglString(_T("Interpolation")), nuiUnitBoolean,
   nuiAttribute<bool>::GetterDelegate(this, &nuiImageSequence::IsInterpolated),
   nuiAttribute<bool>::SetterDelegate(this, &nuiImageSequence::SetInterpolated));

  nuiAttribute<uint32>* AttributeNbFrames = new nuiAttribute<uint32>
  (nglString(_T("NbFrames")), nuiUnitNone,
   nuiAttribute<uint32>::GetterDelegate(this, &nuiImageSequence::GetNbFrames),
   nuiAttribute<uint32>::SetterDelegate(this, &nuiImageSequence::SetNbFrames));

  nuiAttribute<nglString>* AttributeOrientation = new nuiAttribute<nglString>
  (nglString(_T("Orientation")), nuiUnitNone,
   nuiAttribute<nglString>::GetterDelegate(this, &nuiImageSequence::GetOrientation),
   nuiAttribute<nglString>::SetterDelegate(this, &nuiImageSequence::SetOrientation));

	AddAttribute(_T("Color"), AttributeColor);
	AddAttribute(_T("Texture"), AttributeTexture);
	AddAttribute(_T("Interpolation"), AttributeInterpolation);

	AddAttribute(_T("NbFrames"), AttributeNbFrames);
  AddAttribute(_T("Orientation"), AttributeOrientation);
}

nuiImageSequence::~nuiImageSequence()
{
  for (uint32 i = 0; i < mTextures.size(); i++)
    mTextures[i]->Release();
}

bool nuiImageSequence::Load(const nuiXMLNode* pNode)
{
  mColor.SetValue(nuiGetString(pNode, _T("Color"), _T("white")));
  mpTempImage = new nglImage(nglPath(nuiGetString(pNode, _T("Texture"), nglString::Empty)));
  mRefreshTextures = true;

  return true;
}

nuiXMLNode* nuiImageSequence::Serialize(nuiXMLNode* pNode)
{
  pNode->SetName(_T("nuiImageSequence"));
  pNode->SetAttribute(_T("Color"), mColor.GetValue());

  pNode->SetAttribute(_T("Texture"), GetTexturePath());
  return pNode;
}

nuiRect nuiImageSequence::CalcIdealSize()
{
  // create the sequence textures the first time ::CalcIdealSize is called.
  // we don't do it in the decoration initialization because the decoration
  // may have been created from a css stylesheet, and its attributes are set in
  // a undefined order. We need all the attributed to be properly set before creating the textures.
  if (mRefreshTextures)
  {
    NGL_ASSERT(mpTempImage);

    bool res = CreateTextures();
    NGL_ASSERT(res);
    delete mpTempImage;
    mpTempImage = NULL;
    mRefreshTextures = false;
  }

  if (!mTextures.size())
    return mIdealRect;

  mIdealRect.Set(0.0f,0.0f,(nuiSize) mTexRect.GetWidth(),(nuiSize) mTexRect.GetHeight());
  return mIdealRect;
}

bool nuiImageSequence::CreateTextures()
{
  if (!mNbFrames)
    return false;

  if (!mpTempImage && !mTextures.size())
    return false;

  NGL_ASSERT(mpTempImage);

  if (mOrientation == nuiVertical)
    mTexRect.Set(0, 0, mpTempImage->GetWidth(), ToBelow(mpTempImage->GetHeight() / (float)mNbFrames));
  else
    mTexRect.Set(0, 0, ToBelow(mpTempImage->GetWidth() / (float)mNbFrames), mpTempImage->GetHeight());

  // clean existing textures
  for (uint32 i = 0; i < mTextures.size(); i++)
    mTextures[i]->Release();

  char* pBuffer = mpTempImage->GetBuffer();

  // create temp. buffer for destination
  uint32 dstBufferSize = mTexRect.GetWidth() * mTexRect.GetHeight() * 4;
  char* pDst = (char*)malloc(dstBufferSize);
  NGL_ASSERT(pDst);

  //*****************************************************************
  // frames are aligned vertically
  if (mOrientation == nuiVertical)
  {

    // copy and paste each frame from the image to an individual texture
    for (uint32 frame = 0; frame < mNbFrames; frame++)
    {
      uint32 x = 0;
      uint32 y = frame * mTexRect.GetHeight();

      nglImageInfo info;
      mpTempImage->GetInfo(info);
      NGL_ASSERT((info.mPixelFormat == eImagePixelRGB) || (info.mPixelFormat == eImagePixelRGBA))

      char* pSrc = pBuffer + (y * info.mBytesPerLine);

      nglCopyLineFn pFunc = nglGetCopyLineFn(32, info.mBitDepth);
      NGL_ASSERT(pFunc);

      // copy part of the image
      pFunc(pDst, pSrc, mTexRect.GetWidth() * mTexRect.GetHeight(), false/*don't invert*/);

      // create a texture from the copyied buffer and store it
      info.mBufferFormat = eImageFormatRaw;
      info.mPixelFormat = eImagePixelRGBA;
      info.mWidth = mTexRect.GetWidth();
      info.mHeight = mTexRect.GetHeight();
      info.mBitDepth = 32;
      info.mBytesPerPixel = 4;
      info.mBytesPerLine = (mTexRect.GetWidth() * 4);
      info.mpBuffer = pDst;

      nuiTexture* pTex = nuiTexture::GetTexture(info, true/* clone the buffer */);
      mTextures.push_back(pTex);

      if (mInterpolated)
      {
        pTex->SetMinFilter(GL_LINEAR);
        pTex->SetMagFilter(GL_LINEAR);
      }
      else
      {
        pTex->SetMinFilter(GL_NEAREST);
        pTex->SetMagFilter(GL_NEAREST);
      }

    }
  }

  //*****************************************************************
  // frames are aligned horizontally
  else
  {

    // copy and paste each frame from the image to an individual texture
    for (uint32 frame = 0; frame < mNbFrames; frame++)
    {
      uint32 x = frame * mTexRect.GetWidth();

      nglImageInfo info;
      mpTempImage->GetInfo(info);
      NGL_ASSERT((info.mPixelFormat == eImagePixelRGB) || (info.mPixelFormat == eImagePixelRGBA))

      char* pSrc = pBuffer + (x * info.mBytesPerPixel);

      nglCopyLineFn pFunc = nglGetCopyLineFn(32, info.mBitDepth);
      NGL_ASSERT(pFunc);

      char* pDstPtr = pDst;

      // copy line per line
      for (uint32 y = 0; y < mTexRect.GetHeight(); y++)
      {
        pSrc = pBuffer + (y * info.mBytesPerLine) + (x * info.mBytesPerPixel);

        pFunc(pDstPtr, pSrc, mTexRect.GetWidth(), false/*don't invert*/);

        pDstPtr += ((uint32)mTexRect.GetWidth() * 4);
      }

      // create a texture from the copyied buffer and store it
      info.mBufferFormat = eImageFormatRaw;
      info.mPixelFormat = eImagePixelRGBA;
      info.mWidth = mTexRect.GetWidth();
      info.mHeight = mTexRect.GetHeight();
      info.mBitDepth = 32;
      info.mBytesPerPixel = 4;
      info.mBytesPerLine = (mTexRect.GetWidth() * 4);
      info.mpBuffer = pDst;

      nuiTexture* pTex = nuiTexture::GetTexture(info, true/* clone the buffer */);
      mTextures.push_back(pTex);

      if (mInterpolated)
      {
        pTex->SetMinFilter(GL_LINEAR);
        pTex->SetMagFilter(GL_LINEAR);
      }
      else
      {
        pTex->SetMinFilter(GL_NEAREST);
        pTex->SetMagFilter(GL_NEAREST);
      }
    }
  }

  // clean up
  free(pDst);

  return true;
}

uint32 nuiImageSequence::GetFrameIndex(nuiWidget* pWidget) const
{
  return mFrameIndex;
}

void nuiImageSequence::SetFrameIndex(uint32 index)
{
  mFrameIndex = index;
}

uint32 nuiImageSequence::GetNbFrames() const
{
  return mNbFrames;
}

void nuiImageSequence::SetNbFrames(uint32 nbFrames)
{
  mNbFrames = nbFrames;
  mRefreshTextures = true;
}

void nuiImageSequence::SetOrientation(nglString orientation)
{
  if (!orientation.Compare(_T("Vertical"), false))
    mOrientation = nuiVertical;
  else
    mOrientation = nuiHorizontal;

  mRefreshTextures = true;
}

nglString nuiImageSequence::GetOrientation()
{
  if (mOrientation == nuiVertical)
    return nglString(_T("Vertical"));

  return nglString(_T("Horizontal"));
}

const nglPath& nuiImageSequence::GetTexturePath() const
{
  if (HasProperty(_T("Texture")))
    return GetProperty(_T("Texture"));

  return mGlobalTexturePath;
}

void nuiImageSequence::SetTexturePath(const nglPath& rPath)
{
  SetProperty(_T("Texture"), mGlobalTexturePath);
  mpTempImage = new nglImage(rPath);
  NGL_ASSERT(mpTempImage);
  mRefreshTextures = true;

}

// virtual
bool nuiImageSequence::Draw(nuiDrawContext* pContext)
{
  //  int x=0,y=0;
  if (!mTextures.size() || (mFrameIndex >= mTextures.size()))
    return false;

  pContext->PushState();
  pContext->ResetState();
  pContext->SetTexture(mTextures[mFrameIndex]);

  pContext->EnableTexturing(true);

  float alpha = 1.0f;

  pContext->EnableBlending(true);
  pContext->SetBlendFunc(nuiBlendTransp);

  if (mUseAlpha)
  {
    alpha = GetAlpha();
  }

  const nuiRect& destRect = mIdealRect.Size();

  nuiColor color = nuiColor(1.0f, 1.0f, 1.0f, alpha);

  pContext->SetFillColor(color);
  pContext->DrawImage(destRect,mTexRect);

  pContext->EnableBlending(false);
  pContext->EnableTexturing(false);

  pContext->PopState();
  return true;

}

const nuiColor& nuiImageSequence::GetColor() const
{
	return mColor;
}

void nuiImageSequence::SetColor(const nuiColor& color)
{
	mColor = color;
}

bool nuiImageSequence::IsInterpolated()
{
  return mInterpolated;
}

void nuiImageSequence::SetInterpolated(bool set)
{
  mInterpolated = set;

  for (uint32 i = 0; i < mTextures.size(); i++)
  {
    nuiTexture* pTexture = mTextures[i];
    if (mInterpolated)
    {
      pTexture->SetMinFilter(GL_LINEAR);
      pTexture->SetMagFilter(GL_LINEAR);
    }
    else
    {
      pTexture->SetMinFilter(GL_NEAREST);
      pTexture->SetMagFilter(GL_NEAREST);
    }
  }
}

<commit_msg>removed file from bad location<commit_after><|endoftext|>


<commit_before>#include "server.h"

SERVER::SERVER ()
{
        struct addrinfo hints, *servinfo, *p;
        int rv; // return value
        int yes = 1;

        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP

        if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
                exit(EXIT_FAILURE);
	}

	// loop through all the results and bind to the first we can
	for(p = servinfo; p != NULL; p = p->ai_next) {
		if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
			perror("server: socket");
			continue;
		}
		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
			perror("setsockopt");
			exit(1);
		}
		if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
			close(sockfd);
			perror("server: bind");
			continue;
		}
		break;
	}

        if (p == NULL)  {
		std::cerr << "server: failed to bind" << std::endl;
		exit (EXIT_FAILURE);
	}

	freeaddrinfo(servinfo); // all done with this structure

	if (listen(sockfd, BACKLOG) == -1) {
		perror("listen");
		exit(1);
	}
}

SERVER::~SERVER ()
{

}

bool SERVER::addMessage (MESAJ &m)
{
	listamesaje.push_back(m);
	return true;
}

bool SERVER::addClient (CLIENT &c)
{
	listaclienti.push_back(c);
	return true;
}

bool SERVER::removeClient (CLIENT &c)
{
        listaclienti.remove((const CLIENT &)c);
        return true;
}

std::string SERVER::decryptMSG (std::string &msg, CLIENT &sender)
{
        std::string m;

	try{
                m = crypto_box_open (msg, sender.getCI().getNonce(), sender.getCI().getPK(), cryptinfo.getSK());
        }
        catch(char const *e){
                write (STDERR_FILENO, e, 256);
        }
	return m;
}

std::string SERVER::decryptMSG (std::string &msg, std::string &pk, std::string &nonce)
{
        std::string m;

        try{
                m = crypto_box_open (msg, nonce, pk, cryptinfo.getSK());
        }
        catch(char const *e){
                write (STDERR_FILENO, e, 256);
        }
	return m;
}

std::string SERVER::encryptMSG (std::string &msg, CLIENT &receiver)
{
        std::string c;

	try{
                c = crypto_box(msg, cryptinfo.getNonce(), receiver.getCI().getPK(), cryptinfo.getSK());
        }
        catch(char const *e){
                write (STDERR_FILENO, e, 256);
        }
	return c;
}

bool SERVER::sendMessage (std::string &msg, CLIENT &sender)
{
	std::string m = decryptMSG (msg, sender);
	for(std::list<CLIENT>::iterator it = listaclienti.begin(); it != listaclienti.end(); it++){
                std::string cname = encryptMSG (sender.getNume(), *it);
                sendMsgToClient (cname, *it, false);
		std::string c = encryptMSG (m, *it);
		sendMsgToClient (c, *it, false);
                //sendMsgToClient (sender.getNume(), *it, false);
                //sendMsgToClient (msg, *it, false);

	}

	return true;
}

void SERVER::sendMsgToClient (std::string &msg, CLIENT &receiver, bool sendendl)
{
        if(write(receiver.getSFD(), msg.c_str(), msg.size()) == -1){
                std::cerr << "write() error" << std::endl;
                exit (EXIT_FAILURE);
        }
        if(sendendl){
                if(write(receiver.getSFD(), "\n", 1) == -1){
                        std::cerr << "write() error" << std::endl;
                        exit (EXIT_FAILURE);
                }
        }
}

bool SERVER::sendMessageList (CLIENT &receiver)
{
        std::string serialmesaj;
        std::string c_serialmesaj;

        for(std::list<MESAJ>::iterator it = listamesaje.begin(); it != listamesaje.end(); it++){
               //std::string cname = encryptMSG ((*it).getName(), receiver);
               //sendMsgToClient (cname, receiver, true);
               //sleep(1);
               //std::string enc_comment = encryptMSG ((*it).getComment(), receiver);
               //sendMsgToClient (enc_comment, receiver, true);

               serialmesaj += (*it).getName() + (*it).getComment();
        }
        c_serialmesaj = encryptMSG(serialmesaj, receiver);
        sendMsgToClient (c_serialmesaj, receiver, false);

        return true;
}

bool SERVER::verifyName (std::string &nume)
{
        for(std::list<CLIENT>::iterator it = listaclienti.begin(); it != listaclienti.end(); it++){
                if(!nume.compare((*it).getNume()))
                       return false;
        }
        return true;
}

void SERVER::mtxLock ()
{
        mtx.lock();
}

void SERVER::mtxUnlock ()
{
        mtx.unlock();
}

void SERVER::Play ()
{
        int sfd;
        socklen_t sin_size;
        struct sockaddr their_addr; // connector's address information

        while (true){
                sfd = accept(sockfd, &their_addr, &sin_size);
                if(sfd == -1){
                    	perror("accept");
			continue;
                }

                std::thread (client_Communication, this, sfd).detach();
        }
}

CLIENT SERVER::exchangeCIandName (int sfd)
{
        std::string client_pk;
        std::string client_nonce;
        std::string client_name;

        sendPK(sfd);
        sendNonce(sfd);

        client_pk = recvPK(sfd);
        client_nonce =  recvNonce(sfd);

        CRYPTO ci (client_pk, client_nonce);

        client_name = recvName (sfd);

        CLIENT client (ci, sfd, client_name);

        return client;
}

void SERVER::sendPK (int sfd)
{
        if(write (sfd, cryptinfo.getPK().c_str(), crypto_box_PUBLICKEYBYTES ) != crypto_box_PUBLICKEYBYTES){
                perror ("write");
                exit (EXIT_FAILURE);
        }
}

void SERVER::sendNonce (int sfd)
{
        if(write (sfd, cryptinfo.getNonce().c_str(), crypto_box_NONCEBYTES) != crypto_box_NONCEBYTES){
                perror ("write");
                exit (EXIT_FAILURE);
        }
}

std::string SERVER::recvPK (int sfd)
{
        char buf[crypto_box_PUBLICKEYBYTES + 1];

        memset (buf, 0, crypto_box_PUBLICKEYBYTES+1);

        if(read (sfd, buf, crypto_box_PUBLICKEYBYTES) != crypto_box_PUBLICKEYBYTES){
            pthread_exit(NULL);
        }
        std::string server_pk(buf,crypto_box_PUBLICKEYBYTES);
        return server_pk;
}

std::string SERVER::recvNonce (int sfd)
{
        char buf[crypto_box_NONCEBYTES + 1];

        memset (buf, 0, crypto_box_NONCEBYTES + 1);

        if(read (sfd, buf, crypto_box_NONCEBYTES) != crypto_box_NONCEBYTES){
            pthread_exit(NULL);
        }

        std::string server_nonce(buf, crypto_box_NONCEBYTES);
        return server_nonce;
}

std::string SERVER::recvName (int sfd)
{
        char buf[64];
        ssize_t br;

        memset (buf, 0, 64);

        while(true){
                if((br = read (sfd, buf, 64)) == -1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }

                if(!br){}   // EOF
                std::string name(buf,br);
                mtxLock ();
                if(verifyName (name)){
                        // client name free for use
                        mtxUnlock ();
                        if(write (sfd, "Y", 1) != 1){
                                perror ("write");
                                exit (EXIT_FAILURE);
                        }
                        break;
                }
                mtxUnlock ();
                if(write (sfd, "N", 1) != 1){
                        perror ("write");
                        exit (EXIT_FAILURE);
                }
        }

        std::string client_name(buf,br);
        return client_name;
}

// do all the communication with the clients in this thread function
void client_Communication (SERVER *server_p, int sockfd)
{

        CLIENT client = server_p->exchangeCIandName(sockfd);

        server_p->mtxLock();
        server_p->addClient(client);
        server_p->sendMessageList(client);
        server_p->mtxUnlock();

        while (1){
                char bufread[1024];
                ssize_t br;

                memset (bufread, 0, 1024);

                if((br = read (sockfd, bufread, 1024)) == -1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }
                if(!br){    // EOF
                        server_p->removeClient(client);
                        close (sockfd);
                        return;
                }    // blocks until a message arrives

                std::string cmsg(bufread,br);

                std::string msg = server_p->decryptMSG(cmsg, client);

                //construct MESAJ object
                MESAJ mes(client.getNume(), msg);

                server_p->mtxLock();
                server_p->addMessage(mes);  // add message to message list
                server_p->sendMessage(cmsg, client); // send message to the other clients
                server_p->mtxUnlock();
        }
}<commit_msg>remove client when decryption/encryption error occur which normally should't happen so this is because other client programm is used which doesn't respect the protocol used<commit_after>#include "server.h"

SERVER::SERVER ()
{
        struct addrinfo hints, *servinfo, *p;
        int rv; // return value
        int yes = 1;

        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP

        if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
                exit(EXIT_FAILURE);
	}

	// loop through all the results and bind to the first we can
	for(p = servinfo; p != NULL; p = p->ai_next) {
		if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
			perror("server: socket");
			continue;
		}
		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
			perror("setsockopt");
			exit(1);
		}
		if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
			close(sockfd);
			perror("server: bind");
			continue;
		}
		break;
	}

        if (p == NULL)  {
		std::cerr << "server: failed to bind" << std::endl;
		exit (EXIT_FAILURE);
	}

	freeaddrinfo(servinfo); // all done with this structure

	if (listen(sockfd, BACKLOG) == -1) {
		perror("listen");
		exit(1);
	}
}

SERVER::~SERVER ()
{

}

bool SERVER::addMessage (MESAJ &m)
{
	listamesaje.push_back(m);
	return true;
}

bool SERVER::addClient (CLIENT &c)
{
	listaclienti.push_back(c);
	return true;
}

bool SERVER::removeClient (CLIENT &c)
{
        listaclienti.remove((const CLIENT &)c);
        return true;
}

std::string SERVER::decryptMSG (std::string &msg, CLIENT &sender)
{
        std::string m;

	try{
                m = crypto_box_open (msg, sender.getCI().getNonce(), sender.getCI().getPK(), cryptinfo.getSK());
        }
        catch(char const *e){
                write (STDERR_FILENO, e, 256);
                this->removeClient(sender);
                pthread_exit(NULL);
        }
	return m;
}

std::string SERVER::decryptMSG (std::string &msg, std::string &pk, std::string &nonce)
{
        std::string m;

        try{
                m = crypto_box_open (msg, nonce, pk, cryptinfo.getSK());
        }
        catch(char const *e){
                write (STDERR_FILENO, e, 256);
        }
	return m;
}

std::string SERVER::encryptMSG (std::string &msg, CLIENT &receiver)
{
        std::string c;

	try{
                c = crypto_box(msg, cryptinfo.getNonce(), receiver.getCI().getPK(), cryptinfo.getSK());
        }
        catch(char const *e){
                write (STDERR_FILENO, e, 256);
                this->removeClient(receiver);
                pthread_exit(NULL);
        }
	return c;
}

bool SERVER::sendMessage (std::string &msg, CLIENT &sender)
{
	std::string m = decryptMSG (msg, sender);
	for(std::list<CLIENT>::iterator it = listaclienti.begin(); it != listaclienti.end(); it++){
                std::string cname = encryptMSG (sender.getNume(), *it);
                sendMsgToClient (cname, *it, false);
		std::string c = encryptMSG (m, *it);
		sendMsgToClient (c, *it, false);
                //sendMsgToClient (sender.getNume(), *it, false);
                //sendMsgToClient (msg, *it, false);

	}

	return true;
}

void SERVER::sendMsgToClient (std::string &msg, CLIENT &receiver, bool sendendl)
{
        if(write(receiver.getSFD(), msg.c_str(), msg.size()) == -1){
                std::cerr << "write() error" << std::endl;
                exit (EXIT_FAILURE);
        }
        if(sendendl){
                if(write(receiver.getSFD(), "\n", 1) == -1){
                        std::cerr << "write() error" << std::endl;
                        exit (EXIT_FAILURE);
                }
        }
}

bool SERVER::sendMessageList (CLIENT &receiver)
{
        std::string serialmesaj;
        std::string c_serialmesaj;

        for(std::list<MESAJ>::iterator it = listamesaje.begin(); it != listamesaje.end(); it++){
               //std::string cname = encryptMSG ((*it).getName(), receiver);
               //sendMsgToClient (cname, receiver, true);
               //sleep(1);
               //std::string enc_comment = encryptMSG ((*it).getComment(), receiver);
               //sendMsgToClient (enc_comment, receiver, true);

               serialmesaj += (*it).getName() + (*it).getComment();
        }
        c_serialmesaj = encryptMSG(serialmesaj, receiver);
        sendMsgToClient (c_serialmesaj, receiver, false);

        return true;
}

bool SERVER::verifyName (std::string &nume)
{
        for(std::list<CLIENT>::iterator it = listaclienti.begin(); it != listaclienti.end(); it++){
                if(!nume.compare((*it).getNume()))
                       return false;
        }
        return true;
}

void SERVER::mtxLock ()
{
        mtx.lock();
}

void SERVER::mtxUnlock ()
{
        mtx.unlock();
}

void SERVER::Play ()
{
        int sfd;
        socklen_t sin_size;
        struct sockaddr their_addr; // connector's address information

        while (true){
                sfd = accept(sockfd, &their_addr, &sin_size);
                if(sfd == -1){
                    	perror("accept");
			continue;
                }

                std::thread (client_Communication, this, sfd).detach();
        }
}

CLIENT SERVER::exchangeCIandName (int sfd)
{
        std::string client_pk;
        std::string client_nonce;
        std::string client_name;

        sendPK(sfd);
        sendNonce(sfd);

        client_pk = recvPK(sfd);
        client_nonce =  recvNonce(sfd);

        CRYPTO ci (client_pk, client_nonce);

        client_name = recvName (sfd);

        CLIENT client (ci, sfd, client_name);

        return client;
}

void SERVER::sendPK (int sfd)
{
        if(write (sfd, cryptinfo.getPK().c_str(), crypto_box_PUBLICKEYBYTES ) != crypto_box_PUBLICKEYBYTES){
                perror ("write");
                exit (EXIT_FAILURE);
        }
}

void SERVER::sendNonce (int sfd)
{
        if(write (sfd, cryptinfo.getNonce().c_str(), crypto_box_NONCEBYTES) != crypto_box_NONCEBYTES){
                perror ("write");
                exit (EXIT_FAILURE);
        }
}

std::string SERVER::recvPK (int sfd)
{
        char buf[crypto_box_PUBLICKEYBYTES + 1];

        memset (buf, 0, crypto_box_PUBLICKEYBYTES+1);

        if(read (sfd, buf, crypto_box_PUBLICKEYBYTES) != crypto_box_PUBLICKEYBYTES){
            pthread_exit(NULL);
        }
        std::string server_pk(buf,crypto_box_PUBLICKEYBYTES);
        return server_pk;
}

std::string SERVER::recvNonce (int sfd)
{
        char buf[crypto_box_NONCEBYTES + 1];

        memset (buf, 0, crypto_box_NONCEBYTES + 1);

        if(read (sfd, buf, crypto_box_NONCEBYTES) != crypto_box_NONCEBYTES){
            pthread_exit(NULL);
        }

        std::string server_nonce(buf, crypto_box_NONCEBYTES);
        return server_nonce;
}

std::string SERVER::recvName (int sfd)
{
        char buf[64];
        ssize_t br;

        memset (buf, 0, 64);

        while(true){
                if((br = read (sfd, buf, 64)) == -1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }

                if(!br){}   // EOF
                std::string name(buf,br);
                mtxLock ();
                if(verifyName (name)){
                        // client name free for use
                        mtxUnlock ();
                        if(write (sfd, "Y", 1) != 1){
                                perror ("write");
                                exit (EXIT_FAILURE);
                        }
                        break;
                }
                mtxUnlock ();
                if(write (sfd, "N", 1) != 1){
                        perror ("write");
                        exit (EXIT_FAILURE);
                }
        }

        std::string client_name(buf,br);
        return client_name;
}

// do all the communication with the clients in this thread function
void client_Communication (SERVER *server_p, int sockfd)
{

        CLIENT client = server_p->exchangeCIandName(sockfd);

        server_p->mtxLock();
        server_p->addClient(client);
        server_p->sendMessageList(client);
        server_p->mtxUnlock();

        while (1){
                char bufread[1024];
                ssize_t br;

                memset (bufread, 0, 1024);

                if((br = read (sockfd, bufread, 1024)) == -1){
                        perror ("read");
                        exit (EXIT_FAILURE);
                }
                if(!br){    // EOF
                        server_p->removeClient(client);
                        close (sockfd);
                        return;
                }    // blocks until a message arrives

                std::string cmsg(bufread,br);

                std::string msg = server_p->decryptMSG(cmsg, client);

                //construct MESAJ object
                MESAJ mes(client.getNume(), msg);

                server_p->mtxLock();
                server_p->addMessage(mes);  // add message to message list
                server_p->sendMessage(cmsg, client); // send message to the other clients
                server_p->mtxUnlock();
        }
}<|endoftext|>