<commit_before>#include "JianDi.h"

enum CAUSE{
    JIAN_HUN_SHOU_HU=1901,
    YANG_GON=1902,
    JIAN_QI_ZHAN=1903,
    TIAN_SHI_YU_E_MO=1904,
    TIAN_SHI_ZHI_HUN=1905,
    E_MO_ZHI_HUN=1906,
    BU_QU_YI_ZHI=1907
};

JianDi::JianDi()
{
    makeConnection();
    setMyRole(this);

    Button *checkCover;
    checkCover = new Button(10,QStringLiteral("查看剑魂"));
    buttonArea->addOutsideTurnButton(checkCover);

    checkCover->setVisible(true);
    checkCover->setEnabled(true);
    connect(checkCover,SIGNAL(buttonSelected(int)),gui,SLOT(showCoverArea()));
    connect(checkCover,SIGNAL(buttonUnselected(int)),gui,SLOT(closeCoverArea()));
}

void  JianDi::BuQiYiZhi()
{
    state=BU_QU_YI_ZHI;
    gui->reset();
    tipArea->setMsg(QStringLiteral("是否发动不屈意志？"));
    decisionArea->enable(0);
    decisionArea->enable(1);
}

void JianDi::JianHunShouHu()
{
    state=JIAN_HUN_SHOU_HU;
    tipArea->setMsg(QStringLiteral("是否发动剑魂守护？"));
    decisionArea->enable(0);
    decisionArea->enable(1);
}

void JianDi::JianQiZhan(int targetID)
{
    state=JIAN_QI_ZHAN;
    Player* myself=dataInterface->getMyself();
    jianqiID=targetID;      //去除变量jianqiID
    tipArea->setMsg(QStringLiteral("请选择要移除的剑气数："));
    int min=myself->getToken(0)<3?myself->getToken(0):3;
    for(;min>0;min--)
        tipArea->addBoxItem(QString::number(min));
    tipArea->showBox();
    decisionArea->enable(1);

   playerArea->enableAll();
   playerArea->disablePlayerItem(targetID);
   playerArea->setQuota(1);
    decisionArea->disable(0);

}

void JianDi::TianShiZhiHun()
{
    state=TIAN_SHI_ZHI_HUN;
    tipArea->setMsg(QStringLiteral("是否发动天使之魂？如发动请选择剑魂："));
    decisionArea->enable(1);
    decisionArea->disable(0);
    gui->showCoverArea(true);
    HandArea *coverArea = gui->getCoverArea();
    coverArea->reset();
    coverArea->enableAll();
    coverArea->setQuota(1);
}

void JianDi::EMoZhiHun()
{
    state=E_MO_ZHI_HUN;
    tipArea->setMsg(QStringLiteral("是否发动恶魔之魂？如发动请选择剑魂："));
    decisionArea->enable(1);
    decisionArea->disable(0);
    gui->showCoverArea(true);
    HandArea *coverArea = gui->getCoverArea();
    coverArea->reset();
    coverArea->enableAll();
    coverArea->setQuota(1);
}

void JianDi::askForSkill(network::Command* cmd)
{

    if(cmd->respond_id()==JIAN_HUN_SHOU_HU)
         JianHunShouHu();
    else if(cmd->respond_id()==BU_QU_YI_ZHI)
         BuQiYiZhi();
    else if(cmd->respond_id()==JIAN_QI_ZHAN)
         JianQiZhan(cmd->args(0));
    else if(cmd->respond_id()==TIAN_SHI_ZHI_HUN)
         TianShiZhiHun();
    else if(cmd->respond_id()==E_MO_ZHI_HUN)
         EMoZhiHun();
    else
         Role::askForSkill(cmd);
}

void JianDi::coverCardAnalyse()
{
    switch(state)
    {
  case  TIAN_SHI_ZHI_HUN:
  case  E_MO_ZHI_HUN:
        decisionArea->enable(0);
        break;
    }
}

void JianDi::onOkClicked()
{
    Role::onOkClicked();

    QString command;
    QString sourceID;
    QString targetID;
    QString text,cardID;
    QList<Card*> selectedCards = handArea->getSelectedCards();
    QList<Card*> selectedCoverCards = coverArea->getSelectedCards();
    QList<Player*> selectedPlayers = playerArea->getSelectedPlayers();

    network::Respond* respond;

    switch(state)
    {
      case JIAN_HUN_SHOU_HU:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(JIAN_HUN_SHOU_HU);
        respond->add_args(1);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

      case BU_QU_YI_ZHI:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(BU_QU_YI_ZHI);
        respond->add_args(1);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

        case JIAN_QI_ZHAN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(JIAN_QI_ZHAN);
        respond->add_dst_ids(selectedPlayers[0]->getID());
        respond->add_args(1);
        jianqiPoint=tipArea->getBoxCurrentText();
        respond->add_args(jianqiPoint.toInt());
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

      case TIAN_SHI_ZHI_HUN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(TIAN_SHI_ZHI_HUN);
        respond->add_args(1);
        respond->add_card_ids(selectedCoverCards[0]->getID());
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

      case E_MO_ZHI_HUN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(E_MO_ZHI_HUN);
        respond->add_args(1);
        respond->add_card_ids(selectedCoverCards[0]->getID());
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;
    }
    gui->showCoverArea(false);
}

void JianDi::onCancelClicked()
{
    Role::onCancelClicked();

    network::Respond* respond;

    switch(state)
    {
    case JIAN_HUN_SHOU_HU:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(JIAN_HUN_SHOU_HU);
        respond->add_args(0);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

    case BU_QU_YI_ZHI:
      respond = new network::Respond();
      respond->set_src_id(myID);
      respond->set_respond_id(BU_QU_YI_ZHI);
      respond->add_args(0);
      emit sendCommand(network::MSG_RESPOND, respond);
      gui->reset();
      break;

      case JIAN_QI_ZHAN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(JIAN_QI_ZHAN);
        respond->add_args(0);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

      case TIAN_SHI_ZHI_HUN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->add_args(0);
        respond->set_respond_id(TIAN_SHI_ZHI_HUN);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

       case E_MO_ZHI_HUN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(E_MO_ZHI_HUN);
        respond->add_args(0);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;
    }
    gui->showCoverArea(false);
}
<commit_msg>fix bugs on JianDi<commit_after>#include "JianDi.h"

enum CAUSE{
    JIAN_HUN_SHOU_HU=1901,
    YANG_GON=1902,
    JIAN_QI_ZHAN=1903,
    TIAN_SHI_YU_E_MO=1904,
    TIAN_SHI_ZHI_HUN=1905,
    E_MO_ZHI_HUN=1906,
    BU_QU_YI_ZHI=1907
};

JianDi::JianDi()
{
    makeConnection();
    setMyRole(this);

    Button *checkCover;
    checkCover = new Button(10,QStringLiteral("查看剑魂"));
    buttonArea->addOutsideTurnButton(checkCover);

    checkCover->setVisible(true);
    checkCover->setEnabled(true);
    connect(checkCover,SIGNAL(buttonSelected(int)),gui,SLOT(showCoverArea()));
    connect(checkCover,SIGNAL(buttonUnselected(int)),gui,SLOT(closeCoverArea()));
}

void  JianDi::BuQiYiZhi()
{
    state=BU_QU_YI_ZHI;
    gui->reset();
    tipArea->setMsg(QStringLiteral("是否发动不屈意志？"));
    decisionArea->enable(0);
    decisionArea->enable(1);
}

void JianDi::JianHunShouHu()
{
    state=JIAN_HUN_SHOU_HU;
    tipArea->setMsg(QStringLiteral("是否发动剑魂守护？"));
    decisionArea->enable(0);
    decisionArea->enable(1);
    handArea->disableAll();
}

void JianDi::JianQiZhan(int targetID)
{
    state=JIAN_QI_ZHAN;
    Player* myself=dataInterface->getMyself();
    jianqiID=targetID;      //去除变量jianqiID
    tipArea->setMsg(QStringLiteral("请选择要移除的剑气数："));
    int min=myself->getToken(0)<3?myself->getToken(0):3;
    for(;min>0;min--)
        tipArea->addBoxItem(QString::number(min));
    tipArea->showBox();
    decisionArea->enable(1);

   playerArea->enableAll();
   playerArea->disablePlayerItem(targetID);
   playerArea->setQuota(1);
    decisionArea->disable(0);

}

void JianDi::TianShiZhiHun()
{
    state=TIAN_SHI_ZHI_HUN;
    tipArea->setMsg(QStringLiteral("是否发动天使之魂？如发动请选择剑魂："));
    decisionArea->enable(1);
    decisionArea->disable(0);
    gui->showCoverArea(true);
    HandArea *coverArea = gui->getCoverArea();
    coverArea->reset();
    coverArea->enableAll();
    coverArea->setQuota(1);
}

void JianDi::EMoZhiHun()
{
    state=E_MO_ZHI_HUN;
    tipArea->setMsg(QStringLiteral("是否发动恶魔之魂？如发动请选择剑魂："));
    decisionArea->enable(1);
    decisionArea->disable(0);
    gui->showCoverArea(true);
    HandArea *coverArea = gui->getCoverArea();
    coverArea->reset();
    coverArea->enableAll();
    coverArea->setQuota(1);
}

void JianDi::askForSkill(network::Command* cmd)
{

    if(cmd->respond_id()==JIAN_HUN_SHOU_HU)
         JianHunShouHu();
    else if(cmd->respond_id()==BU_QU_YI_ZHI)
         BuQiYiZhi();
    else if(cmd->respond_id()==JIAN_QI_ZHAN)
         JianQiZhan(cmd->args(0));
    else if(cmd->respond_id()==TIAN_SHI_ZHI_HUN)
         TianShiZhiHun();
    else if(cmd->respond_id()==E_MO_ZHI_HUN)
         EMoZhiHun();
    else
         Role::askForSkill(cmd);
}

void JianDi::coverCardAnalyse()
{
    switch(state)
    {
  case  TIAN_SHI_ZHI_HUN:
  case  E_MO_ZHI_HUN:
        decisionArea->enable(0);
        break;
    }
}

void JianDi::onOkClicked()
{
    Role::onOkClicked();

    QString command;
    QString sourceID;
    QString targetID;
    QString text,cardID;
    QList<Card*> selectedCards = handArea->getSelectedCards();
    QList<Card*> selectedCoverCards = coverArea->getSelectedCards();
    QList<Player*> selectedPlayers = playerArea->getSelectedPlayers();

    network::Respond* respond;

    switch(state)
    {
      case JIAN_HUN_SHOU_HU:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(JIAN_HUN_SHOU_HU);
        respond->add_args(1);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

      case BU_QU_YI_ZHI:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(BU_QU_YI_ZHI);
        respond->add_args(1);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

        case JIAN_QI_ZHAN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(JIAN_QI_ZHAN);
        respond->add_dst_ids(selectedPlayers[0]->getID());
        respond->add_args(1);
        jianqiPoint=tipArea->getBoxCurrentText();
        respond->add_args(jianqiPoint.toInt());
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

      case TIAN_SHI_ZHI_HUN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(TIAN_SHI_ZHI_HUN);
        respond->add_args(1);
        respond->add_card_ids(selectedCoverCards[0]->getID());
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

      case E_MO_ZHI_HUN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(E_MO_ZHI_HUN);
        respond->add_args(1);
        respond->add_card_ids(selectedCoverCards[0]->getID());
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;
    }
    gui->showCoverArea(false);
}

void JianDi::onCancelClicked()
{
    Role::onCancelClicked();

    network::Respond* respond;

    switch(state)
    {
    case JIAN_HUN_SHOU_HU:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(JIAN_HUN_SHOU_HU);
        respond->add_args(0);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

    case BU_QU_YI_ZHI:
      respond = new network::Respond();
      respond->set_src_id(myID);
      respond->set_respond_id(BU_QU_YI_ZHI);
      respond->add_args(0);
      emit sendCommand(network::MSG_RESPOND, respond);
      gui->reset();
      break;

      case JIAN_QI_ZHAN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(JIAN_QI_ZHAN);
        respond->add_args(0);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

      case TIAN_SHI_ZHI_HUN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->add_args(0);
        respond->set_respond_id(TIAN_SHI_ZHI_HUN);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;

       case E_MO_ZHI_HUN:
        respond = new network::Respond();
        respond->set_src_id(myID);
        respond->set_respond_id(E_MO_ZHI_HUN);
        respond->add_args(0);
        emit sendCommand(network::MSG_RESPOND, respond);
        gui->reset();
        break;
    }
    gui->showCoverArea(false);
}
<|endoftext|>


<commit_before>//=============================================================================================================
/**
 * @file     quickcontrolview.cpp
 * @author   Lorenz Esch <lesch@mgh.harvard.edu>
 * @since    0.1.0
 * @date     June, 2015
 *
 * @section  LICENSE
 *
 * Copyright (C) 2015, Lorenz Esch. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    Definition of the QuickControlView Class.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "ui_quickcontrolview.h"

#include "quickcontrolview.h"

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QGroupBox>
#include <QTabWidget>
#include <QSettings>
#include <QApplication>
#include <QDesktopWidget>
#include <QDebug>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace DISPLIB;

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

QuickControlView::QuickControlView(const QString &sSettingsPath,
                                   const QString& name,
                                   Qt::WindowFlags flags,
                                   QWidget *parent,
                                   bool bDraggable)
: DraggableFramelessWidget(parent, flags, false, bDraggable, true)
, ui(new Ui::QuickControlViewWidget)
, m_sName(name)
, m_sSettingsPath(sSettingsPath)
{
    ui->setupUi(this);
    ui->m_pTabWidget->setTabBarAutoHide(true);
    ui->m_pTabWidget->setMovable(true);
    this->setWindowTitle("Quick Control");

    if(!(windowFlags() & Qt::CustomizeWindowHint)) {
        ui->m_pushButton_close->hide();
    }

    //Init opacity slider
    connect(ui->m_horizontalSlider_opacity, &QSlider::valueChanged,
            this, &QuickControlView::onOpacityChange);

    //Init and connect close button
    connect(ui->m_pushButton_close, static_cast<void (QPushButton::*)(bool)>(&QPushButton::clicked),
            this, &QuickControlView::hide);

    this->adjustSize();

    loadSettings(m_sSettingsPath);
}

//=============================================================================================================

QuickControlView::~QuickControlView()
{
    saveSettings(m_sSettingsPath);

    delete ui;
}

//=============================================================================================================

void QuickControlView::clear()
{
    while(ui->m_pTabWidget->count() != 0) {
        QWidget* pTabWidget = ui->m_pTabWidget->widget(ui->m_pTabWidget->count()-1);
        ui->m_pTabWidget->removeTab(ui->m_pTabWidget->count()-1);
        delete pTabWidget;
    }
}

//=============================================================================================================

QVBoxLayout* QuickControlView::findTabWidgetLayout(const QString& sTabName)
{
    QVBoxLayout* pTabWidgetLayout = Q_NULLPTR;

    if(QWidget* pTabWidget = ui->m_pTabWidget->findChild<QWidget *>(sTabName + "TabWidget")) {
        // Tab widget already exisits. Get the grid layout and return it.
        pTabWidgetLayout = qobject_cast<QVBoxLayout *>(pTabWidget->layout());
    } else {
        // Tab widget does not exist yet. Create it and return grid lyout.
        pTabWidget = new QWidget();
        pTabWidget->setObjectName(sTabName + "TabWidget");
        pTabWidgetLayout = new QVBoxLayout();
        pTabWidgetLayout->setContentsMargins(4,2,4,4);
        pTabWidget->setLayout(pTabWidgetLayout);
        ui->m_pTabWidget->insertTab(0,pTabWidget, sTabName);
    }

    return pTabWidgetLayout;
}

//=============================================================================================================

void QuickControlView::addWidgets(const QList<QWidget*>& lWidgets,
                                  const QString& sTabName,
                                  bool bAddToEnd)
{
    for(int i = 0; i < lWidgets.size(); ++i) {
        QString sObjectName = lWidgets.at(i)->objectName();

        if(sObjectName.contains("widget_", Qt::CaseInsensitive)) {
            this->addWidget(lWidgets.at(i), sTabName, bAddToEnd);
        }

        if(sObjectName.contains("group_", Qt::CaseInsensitive)) {
            if(sObjectName.contains("group_tab_", Qt::CaseInsensitive)) {
                sObjectName.remove("group_tab_");
                QStringList sList = sObjectName.split("_");

                if(sList.size() >= 2) {
                    this->addGroupBoxWithTabs(lWidgets.at(i), sList.at(0), sList.at(1), sTabName, bAddToEnd);
                } else {
                    this->addGroupBoxWithTabs(lWidgets.at(i), "", sObjectName, sTabName, bAddToEnd);
                }
            } else {
                sObjectName.remove("group_");
                this->addGroupBox(lWidgets.at(i), sObjectName, sTabName, bAddToEnd);
            }
        }
    }
}

//=============================================================================================================

void QuickControlView::addWidget(QWidget* pWidget,
                                 const QString& sTabName,
                                 bool bAddToEnd)
{
    if(QVBoxLayout* pTabWidgetLayout = findTabWidgetLayout(sTabName)) {
        int iPos = bAddToEnd ? -1 : 0;
        pTabWidgetLayout->insertWidget(iPos,
                                       pWidget,
                                       0);
    }
}

//=============================================================================================================

void QuickControlView::addGroupBox(QWidget* pWidget,
                                   const QString& sGroupBoxName,
                                   const QString& sTabName,
                                   bool bAddToEnd)
{
    if(QVBoxLayout* pTabWidgetLayout = findTabWidgetLayout(sTabName)) {
        int iPos = bAddToEnd ? -1 : 0;
        QGroupBox* pGroupBox = new QGroupBox(sGroupBoxName);
        pGroupBox->setObjectName(sGroupBoxName);

        QVBoxLayout *pVBox = new QVBoxLayout;

        pVBox->setContentsMargins(0,0,0,0);
        pVBox->addWidget(pWidget);
        pGroupBox->setLayout(pVBox);

        pTabWidgetLayout->insertWidget(iPos,
                                       pGroupBox,
                                       0);
    }
}

//=============================================================================================================

void QuickControlView::addGroupBoxWithTabs(QWidget* pWidget,
                                           const QString& sGroupBoxName,
                                           const QString& sTabNameGroupBox,
                                           const QString& sTabName,
                                           bool bAddToEnd)
{
    if(QVBoxLayout* pTabWidgetLayout = findTabWidgetLayout(sTabName)) {
        QGroupBox* pGroupBox = pTabWidgetLayout->parentWidget()->findChild<QGroupBox *>(sGroupBoxName);

        if(!pGroupBox) {
            int iPos = bAddToEnd ? -1 : 0;
            pGroupBox = new QGroupBox(sGroupBoxName);
            pGroupBox->setObjectName(sGroupBoxName);

            pTabWidgetLayout->insertWidget(iPos,
                                           pGroupBox,
                                           0);

            QVBoxLayout *pVBox = new QVBoxLayout;
            QTabWidget* pTabWidget = new QTabWidget;
            pTabWidget->setTabBarAutoHide(false);
            pTabWidget->setMovable(true);
            pTabWidget->setObjectName(sGroupBoxName + "TabWidget");

            pTabWidget->addTab(pWidget, sTabNameGroupBox);
            pVBox->setContentsMargins(4,2,4,4);
            pVBox->addWidget(pTabWidget);
            pGroupBox->setLayout(pVBox);
        } else {
            QTabWidget* pTabWidget = pGroupBox->findChild<QTabWidget *>(sGroupBoxName + "TabWidget");

            if(pTabWidget) {
                pTabWidget->addTab(pWidget, sTabNameGroupBox);
            }
        }
    }
}

//=============================================================================================================

void QuickControlView::setOpacityValue(int opactiy)
{
    ui->m_horizontalSlider_opacity->setValue(opactiy);

    onOpacityChange(opactiy);
}

//=============================================================================================================

int QuickControlView::getOpacityValue()
{
    return ui->m_horizontalSlider_opacity->value();
}

//=============================================================================================================

void QuickControlView::setVisiblityHideOpacityClose(bool bVisibility)
{
    ui->m_pushButton_close->setVisible(bVisibility);
    ui->m_horizontalSlider_opacity->setVisible(bVisibility);
    ui->m_label_opacity->setVisible(bVisibility);
}

//=============================================================================================================

void QuickControlView::saveSettings(const QString& settingsPath)
{
    if(settingsPath.isEmpty()) {
        return;
    }

    QSettings settings;

    settings.setValue(settingsPath + QString("/QuickControlViewOpacity"), getOpacityValue());
    settings.setValue(settingsPath + QString("/QuickControlViewPos"), this->pos());
}

//=============================================================================================================

void QuickControlView::loadSettings(const QString& settingsPath)
{
    if(settingsPath.isEmpty()) {
        return;
    }

    QSettings settings;

    setOpacityValue(settings.value(settingsPath + QString("/QuickControlViewOpacity"), 100).toInt());

    QPoint pos = settings.value(settingsPath + QString("/QuickControlViewPos"), QPoint(100,100)).toPoint();

    QRect screenRect = QApplication::desktop()->screenGeometry();
    if(!screenRect.contains(pos) && QGuiApplication::screens().size() == 1) {
        move(QPoint(100,100));
    } else {
        move(pos);
    }
}

//=============================================================================================================

void QuickControlView::onOpacityChange(qint32 value)
{
    if(value <= 0) {
        this->setWindowOpacity(1);
    } else {
        this->setWindowOpacity(1/(100.0/value));
    }
}
<commit_msg>ENH: Change tab row to vertical in QuickControlView<commit_after>//=============================================================================================================
/**
 * @file     quickcontrolview.cpp
 * @author   Lorenz Esch <lesch@mgh.harvard.edu>
 * @since    0.1.0
 * @date     June, 2015
 *
 * @section  LICENSE
 *
 * Copyright (C) 2015, Lorenz Esch. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    Definition of the QuickControlView Class.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "ui_quickcontrolview.h"

#include "quickcontrolview.h"

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QGroupBox>
#include <QTabWidget>
#include <QSettings>
#include <QApplication>
#include <QDesktopWidget>
#include <QDebug>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace DISPLIB;

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

QuickControlView::QuickControlView(const QString &sSettingsPath,
                                   const QString& name,
                                   Qt::WindowFlags flags,
                                   QWidget *parent,
                                   bool bDraggable)
: DraggableFramelessWidget(parent, flags, false, bDraggable, true)
, ui(new Ui::QuickControlViewWidget)
, m_sName(name)
, m_sSettingsPath(sSettingsPath)
{
    ui->setupUi(this);
    ui->m_pTabWidget->setTabBarAutoHide(true);
    ui->m_pTabWidget->setMovable(true);
    ui->m_pTabWidget->setTabPosition(QTabWidget::West);
    this->setWindowTitle("Quick Control");

    if(!(windowFlags() & Qt::CustomizeWindowHint)) {
        ui->m_pushButton_close->hide();
    }

    //Init opacity slider
    connect(ui->m_horizontalSlider_opacity, &QSlider::valueChanged,
            this, &QuickControlView::onOpacityChange);

    //Init and connect close button
    connect(ui->m_pushButton_close, static_cast<void (QPushButton::*)(bool)>(&QPushButton::clicked),
            this, &QuickControlView::hide);

    this->adjustSize();

    loadSettings(m_sSettingsPath);
}

//=============================================================================================================

QuickControlView::~QuickControlView()
{
    saveSettings(m_sSettingsPath);

    delete ui;
}

//=============================================================================================================

void QuickControlView::clear()
{
    while(ui->m_pTabWidget->count() != 0) {
        QWidget* pTabWidget = ui->m_pTabWidget->widget(ui->m_pTabWidget->count()-1);
        ui->m_pTabWidget->removeTab(ui->m_pTabWidget->count()-1);
        delete pTabWidget;
    }
}

//=============================================================================================================

QVBoxLayout* QuickControlView::findTabWidgetLayout(const QString& sTabName)
{
    QVBoxLayout* pTabWidgetLayout = Q_NULLPTR;

    if(QWidget* pTabWidget = ui->m_pTabWidget->findChild<QWidget *>(sTabName + "TabWidget")) {
        // Tab widget already exisits. Get the grid layout and return it.
        pTabWidgetLayout = qobject_cast<QVBoxLayout *>(pTabWidget->layout());
    } else {
        // Tab widget does not exist yet. Create it and return grid lyout.
        pTabWidget = new QWidget();
        pTabWidget->setObjectName(sTabName + "TabWidget");
        pTabWidgetLayout = new QVBoxLayout();
        pTabWidgetLayout->setContentsMargins(4,2,4,4);
        pTabWidget->setLayout(pTabWidgetLayout);
        ui->m_pTabWidget->insertTab(0,pTabWidget, sTabName);
    }

    return pTabWidgetLayout;
}

//=============================================================================================================

void QuickControlView::addWidgets(const QList<QWidget*>& lWidgets,
                                  const QString& sTabName,
                                  bool bAddToEnd)
{
    for(int i = 0; i < lWidgets.size(); ++i) {
        QString sObjectName = lWidgets.at(i)->objectName();

        if(sObjectName.contains("widget_", Qt::CaseInsensitive)) {
            this->addWidget(lWidgets.at(i), sTabName, bAddToEnd);
        }

        if(sObjectName.contains("group_", Qt::CaseInsensitive)) {
            if(sObjectName.contains("group_tab_", Qt::CaseInsensitive)) {
                sObjectName.remove("group_tab_");
                QStringList sList = sObjectName.split("_");

                if(sList.size() >= 2) {
                    this->addGroupBoxWithTabs(lWidgets.at(i), sList.at(0), sList.at(1), sTabName, bAddToEnd);
                } else {
                    this->addGroupBoxWithTabs(lWidgets.at(i), "", sObjectName, sTabName, bAddToEnd);
                }
            } else {
                sObjectName.remove("group_");
                this->addGroupBox(lWidgets.at(i), sObjectName, sTabName, bAddToEnd);
            }
        }
    }
}

//=============================================================================================================

void QuickControlView::addWidget(QWidget* pWidget,
                                 const QString& sTabName,
                                 bool bAddToEnd)
{
    if(QVBoxLayout* pTabWidgetLayout = findTabWidgetLayout(sTabName)) {
        int iPos = bAddToEnd ? -1 : 0;
        pTabWidgetLayout->insertWidget(iPos,
                                       pWidget,
                                       0);
    }
}

//=============================================================================================================

void QuickControlView::addGroupBox(QWidget* pWidget,
                                   const QString& sGroupBoxName,
                                   const QString& sTabName,
                                   bool bAddToEnd)
{
    if(QVBoxLayout* pTabWidgetLayout = findTabWidgetLayout(sTabName)) {
        int iPos = bAddToEnd ? -1 : 0;
        QGroupBox* pGroupBox = new QGroupBox(sGroupBoxName);
        pGroupBox->setObjectName(sGroupBoxName);

        QVBoxLayout *pVBox = new QVBoxLayout;

        pVBox->setContentsMargins(0,0,0,0);
        pVBox->addWidget(pWidget);
        pGroupBox->setLayout(pVBox);

        pTabWidgetLayout->insertWidget(iPos,
                                       pGroupBox,
                                       0);
    }
}

//=============================================================================================================

void QuickControlView::addGroupBoxWithTabs(QWidget* pWidget,
                                           const QString& sGroupBoxName,
                                           const QString& sTabNameGroupBox,
                                           const QString& sTabName,
                                           bool bAddToEnd)
{
    if(QVBoxLayout* pTabWidgetLayout = findTabWidgetLayout(sTabName)) {
        QGroupBox* pGroupBox = pTabWidgetLayout->parentWidget()->findChild<QGroupBox *>(sGroupBoxName);

        if(!pGroupBox) {
            int iPos = bAddToEnd ? -1 : 0;
            pGroupBox = new QGroupBox(sGroupBoxName);
            pGroupBox->setObjectName(sGroupBoxName);

            pTabWidgetLayout->insertWidget(iPos,
                                           pGroupBox,
                                           0);

            QVBoxLayout *pVBox = new QVBoxLayout;
            QTabWidget* pTabWidget = new QTabWidget;
            pTabWidget->setTabBarAutoHide(false);
            pTabWidget->setMovable(true);
            pTabWidget->setObjectName(sGroupBoxName + "TabWidget");

            pTabWidget->addTab(pWidget, sTabNameGroupBox);
            pVBox->setContentsMargins(4,2,4,4);
            pVBox->addWidget(pTabWidget);
            pGroupBox->setLayout(pVBox);
        } else {
            QTabWidget* pTabWidget = pGroupBox->findChild<QTabWidget *>(sGroupBoxName + "TabWidget");

            if(pTabWidget) {
                pTabWidget->addTab(pWidget, sTabNameGroupBox);
            }
        }
    }
}

//=============================================================================================================

void QuickControlView::setOpacityValue(int opactiy)
{
    ui->m_horizontalSlider_opacity->setValue(opactiy);

    onOpacityChange(opactiy);
}

//=============================================================================================================

int QuickControlView::getOpacityValue()
{
    return ui->m_horizontalSlider_opacity->value();
}

//=============================================================================================================

void QuickControlView::setVisiblityHideOpacityClose(bool bVisibility)
{
    ui->m_pushButton_close->setVisible(bVisibility);
    ui->m_horizontalSlider_opacity->setVisible(bVisibility);
    ui->m_label_opacity->setVisible(bVisibility);
}

//=============================================================================================================

void QuickControlView::saveSettings(const QString& settingsPath)
{
    if(settingsPath.isEmpty()) {
        return;
    }

    QSettings settings;

    settings.setValue(settingsPath + QString("/QuickControlViewOpacity"), getOpacityValue());
    settings.setValue(settingsPath + QString("/QuickControlViewPos"), this->pos());
}

//=============================================================================================================

void QuickControlView::loadSettings(const QString& settingsPath)
{
    if(settingsPath.isEmpty()) {
        return;
    }

    QSettings settings;

    setOpacityValue(settings.value(settingsPath + QString("/QuickControlViewOpacity"), 100).toInt());

    QPoint pos = settings.value(settingsPath + QString("/QuickControlViewPos"), QPoint(100,100)).toPoint();

    QRect screenRect = QApplication::desktop()->screenGeometry();
    if(!screenRect.contains(pos) && QGuiApplication::screens().size() == 1) {
        move(QPoint(100,100));
    } else {
        move(pos);
    }
}

//=============================================================================================================

void QuickControlView::onOpacityChange(qint32 value)
{
    if(value <= 0) {
        this->setWindowOpacity(1);
    } else {
        this->setWindowOpacity(1/(100.0/value));
    }
}
<|endoftext|>


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

#include "ExpectMonitor.hxx"
#include "MonitorHandler.hxx"
#include "MonitorClass.hxx"
#include "MonitorConfig.hxx"
#include "system/Error.hxx"
#include "net/UniqueSocketDescriptor.hxx"
#include "net/SocketAddress.hxx"
#include "event/net/ConnectSocket.hxx"
#include "event/SocketEvent.hxx"
#include "event/TimerEvent.hxx"
#include "util/Cancellable.hxx"

#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>

class ExpectMonitor final : ConnectSocketHandler, Cancellable {
    const LbMonitorConfig &config;

    ConnectSocket connect;

    SocketDescriptor fd = SocketDescriptor::Undefined();

    SocketEvent event;
    TimerEvent timeout_event;

    /**
     * A timer which is used to delay the recv() call, just in case
     * the server sends the response in more than one packet.
     */
    TimerEvent delay_event;

    LbMonitorHandler &handler;

public:
    ExpectMonitor(EventLoop &event_loop,
                  const LbMonitorConfig &_config,
                  LbMonitorHandler &_handler)
        :config(_config),
         connect(event_loop, *this),
         event(event_loop, BIND_THIS_METHOD(EventCallback)),
         timeout_event(event_loop, BIND_THIS_METHOD(OnTimeout)),
         delay_event(event_loop, BIND_THIS_METHOD(DelayCallback)),
         handler(_handler) {}

    ExpectMonitor(const ExpectMonitor &other) = delete;

    void Start(SocketAddress address, CancellablePointer &cancel_ptr) {
        cancel_ptr = *this;

        const Event::Duration zero{};
        const auto timeout = config.connect_timeout > zero
            ? config.connect_timeout
            : (config.timeout > zero
               ? config.timeout
               : std::chrono::seconds(30));

        connect.Connect(address, timeout);
    }

private:
    /* virtual methods from class Cancellable */
    void Cancel() noexcept override;

    /* virtual methods from class ConnectSocketHandler */
    void OnSocketConnectSuccess(UniqueSocketDescriptor &&fd) noexcept override;

    void OnSocketConnectTimeout() noexcept override {
        handler.Timeout();
        delete this;
    }

    void OnSocketConnectError(std::exception_ptr ep) noexcept override {
        handler.Error(ep);
        delete this;
    }

private:
    void EventCallback(unsigned events);
    void OnTimeout() noexcept;
    void DelayCallback();
};

static bool
check_expectation(char *received, size_t received_length,
                  const char *expect)
{
    return memmem(received, received_length, expect, strlen(expect)) != nullptr;
}

/*
 * async operation
 *
 */

void
ExpectMonitor::Cancel() noexcept
{
    if (fd.IsDefined()) {
        event.Cancel();
        timeout_event.Cancel();
        delay_event.Cancel();
        fd.Close();
    }

    delete this;
}

/*
 * libevent callback
 *
 */

inline void
ExpectMonitor::EventCallback(unsigned)
{
    event.Cancel();

    /* wait 10ms before we start reading */
    delay_event.Schedule(std::chrono::milliseconds(10));
}

inline void
ExpectMonitor::OnTimeout() noexcept
{
    fd.Close();
    handler.Timeout();

    delete this;
}

void
ExpectMonitor::DelayCallback()
{
    char buffer[1024];

    ssize_t nbytes = recv(fd.Get(), buffer, sizeof(buffer),
                          MSG_DONTWAIT);
    if (nbytes < 0) {
        auto e = MakeErrno("Failed to receive");
        fd.Close();
        handler.Error(std::make_exception_ptr(e));
    } else if (!config.fade_expect.empty() &&
               check_expectation(buffer, nbytes,
                                 config.fade_expect.c_str())) {
        fd.Close();
        handler.Fade();
    } else if (config.expect.empty() ||
               check_expectation(buffer, nbytes,
                                 config.expect.c_str())) {
        fd.Close();
        handler.Success();
    } else {
        fd.Close();
        handler.Error(std::make_exception_ptr(std::runtime_error("Expectation failed")));
    }

    delete this;
}

/*
 * client_socket handler
 *
 */

void
ExpectMonitor::OnSocketConnectSuccess(UniqueSocketDescriptor &&new_fd) noexcept
{
    if (!config.send.empty()) {
        ssize_t nbytes = send(new_fd.Get(), config.send.data(),
                              config.send.length(),
                              MSG_DONTWAIT);
        if (nbytes < 0) {
            handler.Error(std::make_exception_ptr(MakeErrno("Failed to send")));
            delete this;
            return;
        }
    }

    const auto expect_timeout = config.timeout > Event::Duration{}
        ? config.timeout
        : std::chrono::seconds(10);

    fd = new_fd.Release();
    event.Open(fd);
    event.ScheduleRead();
    timeout_event.Schedule(expect_timeout);
}

/*
 * lb_monitor_class
 *
 */

static void
expect_monitor_run(EventLoop &event_loop,
                   const LbMonitorConfig &config,
                   SocketAddress address,
                   LbMonitorHandler &handler,
                   CancellablePointer &cancel_ptr)
{
    ExpectMonitor *expect = new ExpectMonitor(event_loop, config,
                                              handler);

    expect->Start(address, cancel_ptr);
}

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

#include "ExpectMonitor.hxx"
#include "MonitorHandler.hxx"
#include "MonitorClass.hxx"
#include "MonitorConfig.hxx"
#include "system/Error.hxx"
#include "net/UniqueSocketDescriptor.hxx"
#include "net/SocketAddress.hxx"
#include "event/net/ConnectSocket.hxx"
#include "event/SocketEvent.hxx"
#include "event/TimerEvent.hxx"
#include "util/Cancellable.hxx"

#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>

class ExpectMonitor final : ConnectSocketHandler, Cancellable {
    const LbMonitorConfig &config;

    ConnectSocket connect;

    SocketDescriptor fd = SocketDescriptor::Undefined();

    SocketEvent event;
    TimerEvent timeout_event;

    /**
     * A timer which is used to delay the recv() call, just in case
     * the server sends the response in more than one packet.
     */
    TimerEvent delay_event;

    LbMonitorHandler &handler;

public:
    ExpectMonitor(EventLoop &event_loop,
                  const LbMonitorConfig &_config,
                  LbMonitorHandler &_handler) noexcept
        :config(_config),
         connect(event_loop, *this),
         event(event_loop, BIND_THIS_METHOD(EventCallback)),
         timeout_event(event_loop, BIND_THIS_METHOD(OnTimeout)),
         delay_event(event_loop, BIND_THIS_METHOD(DelayCallback)),
         handler(_handler) {}

    ExpectMonitor(const ExpectMonitor &other) = delete;

    void Start(SocketAddress address, CancellablePointer &cancel_ptr) noexcept {
        cancel_ptr = *this;

        const Event::Duration zero{};
        const auto timeout = config.connect_timeout > zero
            ? config.connect_timeout
            : (config.timeout > zero
               ? config.timeout
               : std::chrono::seconds(30));

        connect.Connect(address, timeout);
    }

private:
    /* virtual methods from class Cancellable */
    void Cancel() noexcept override;

    /* virtual methods from class ConnectSocketHandler */
    void OnSocketConnectSuccess(UniqueSocketDescriptor &&fd) noexcept override;

    void OnSocketConnectTimeout() noexcept override {
        handler.Timeout();
        delete this;
    }

    void OnSocketConnectError(std::exception_ptr ep) noexcept override {
        handler.Error(ep);
        delete this;
    }

private:
    void EventCallback(unsigned events) noexcept;
    void OnTimeout() noexcept;
    void DelayCallback() noexcept;
};

static bool
check_expectation(char *received, size_t received_length,
                  const char *expect) noexcept
{
    return memmem(received, received_length, expect, strlen(expect)) != nullptr;
}

/*
 * async operation
 *
 */

void
ExpectMonitor::Cancel() noexcept
{
    if (fd.IsDefined()) {
        event.Cancel();
        timeout_event.Cancel();
        delay_event.Cancel();
        fd.Close();
    }

    delete this;
}

/*
 * libevent callback
 *
 */

inline void
ExpectMonitor::EventCallback(unsigned) noexcept
{
    event.Cancel();

    /* wait 10ms before we start reading */
    delay_event.Schedule(std::chrono::milliseconds(10));
}

inline void
ExpectMonitor::OnTimeout() noexcept
{
    fd.Close();
    handler.Timeout();

    delete this;
}

void
ExpectMonitor::DelayCallback() noexcept
{
    char buffer[1024];

    ssize_t nbytes = recv(fd.Get(), buffer, sizeof(buffer),
                          MSG_DONTWAIT);
    if (nbytes < 0) {
        auto e = MakeErrno("Failed to receive");
        fd.Close();
        handler.Error(std::make_exception_ptr(e));
    } else if (!config.fade_expect.empty() &&
               check_expectation(buffer, nbytes,
                                 config.fade_expect.c_str())) {
        fd.Close();
        handler.Fade();
    } else if (config.expect.empty() ||
               check_expectation(buffer, nbytes,
                                 config.expect.c_str())) {
        fd.Close();
        handler.Success();
    } else {
        fd.Close();
        handler.Error(std::make_exception_ptr(std::runtime_error("Expectation failed")));
    }

    delete this;
}

/*
 * client_socket handler
 *
 */

void
ExpectMonitor::OnSocketConnectSuccess(UniqueSocketDescriptor &&new_fd) noexcept
{
    if (!config.send.empty()) {
        ssize_t nbytes = send(new_fd.Get(), config.send.data(),
                              config.send.length(),
                              MSG_DONTWAIT);
        if (nbytes < 0) {
            handler.Error(std::make_exception_ptr(MakeErrno("Failed to send")));
            delete this;
            return;
        }
    }

    const auto expect_timeout = config.timeout > Event::Duration{}
        ? config.timeout
        : std::chrono::seconds(10);

    fd = new_fd.Release();
    event.Open(fd);
    event.ScheduleRead();
    timeout_event.Schedule(expect_timeout);
}

/*
 * lb_monitor_class
 *
 */

static void
expect_monitor_run(EventLoop &event_loop,
                   const LbMonitorConfig &config,
                   SocketAddress address,
                   LbMonitorHandler &handler,
                   CancellablePointer &cancel_ptr)
{
    ExpectMonitor *expect = new ExpectMonitor(event_loop, config,
                                              handler);

    expect->Start(address, cancel_ptr);
}

const LbMonitorClass expect_monitor_class = {
    .run = expect_monitor_run,
};
<|endoftext|>


<commit_before>/**
 * @file llstyle.cpp
 * @brief Text style class
 *
 * $LicenseInfo:firstyear=2001&license=viewergpl$
 *
 * Copyright (c) 2001-2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "linden_common.h"

#include "llstyle.h"

#include "llfontgl.h"
#include "llstring.h"
#include "llui.h"

LLStyle::Params::Params()
:	visible("visible", true),
	drop_shadow("drop_shadow", LLFontGL::NO_SHADOW),
	color("color", LLColor4::black),
	font("font", LLFontGL::getFontMonospace()),
	image("image"),
	link_href("href")
{}

LLStyle::LLStyle(const LLStyle::Params& p)
:	mVisible(p.visible),
	mColor(p.color()),
	mReadOnlyColor(p.readonly_color()),
	mFont(p.font()),
	mLink(p.link_href),
	mDropShadow(p.drop_shadow),
	mImagep(p.image())
{}

void LLStyle::setFont(const LLFontGL* font)
{
	mFont = font;
}

const LLFontGL* LLStyle::getFont() const
{
	return mFont;
}

void LLStyle::setLinkHREF(const std::string& href)
{
	mLink = href;
}

BOOL LLStyle::isLink() const
{
	return mLink.size();
}

BOOL LLStyle::isVisible() const
{
	return mVisible;
}

void LLStyle::setVisible(BOOL is_visible)
{
	mVisible = is_visible;
}

LLUIImagePtr LLStyle::getImage() const
{
	return mImagep;
}

void LLStyle::setImage(const LLUUID& src)
{
	mImagep = LLUI::getUIImageByID(src);
}

void LLStyle::setImage(const std::string& name)
{
	mImagep = LLUI::getUIImage(name);
}
<commit_msg>CID-324<commit_after>/**
 * @file llstyle.cpp
 * @brief Text style class
 *
 * $LicenseInfo:firstyear=2001&license=viewergpl$
 *
 * Copyright (c) 2001-2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "linden_common.h"

#include "llstyle.h"

#include "llfontgl.h"
#include "llstring.h"
#include "llui.h"

LLStyle::Params::Params()
:	visible("visible", true),
	drop_shadow("drop_shadow", LLFontGL::NO_SHADOW),
	color("color", LLColor4::black),
	font("font", LLFontGL::getFontMonospace()),
	image("image"),
	link_href("href")
{}

LLStyle::LLStyle(const LLStyle::Params& p)
:	mItalic(FALSE),
	mBold(FALSE),
	mUnderline(FALSE),
	mVisible(p.visible),
	mColor(p.color()),
	mReadOnlyColor(p.readonly_color()),
	mFont(p.font()),
	mLink(p.link_href),
	mDropShadow(p.drop_shadow),
	mImagep(p.image())
{}

void LLStyle::setFont(const LLFontGL* font)
{
	mFont = font;
}

const LLFontGL* LLStyle::getFont() const
{
	return mFont;
}

void LLStyle::setLinkHREF(const std::string& href)
{
	mLink = href;
}

BOOL LLStyle::isLink() const
{
	return mLink.size();
}

BOOL LLStyle::isVisible() const
{
	return mVisible;
}

void LLStyle::setVisible(BOOL is_visible)
{
	mVisible = is_visible;
}

LLUIImagePtr LLStyle::getImage() const
{
	return mImagep;
}

void LLStyle::setImage(const LLUUID& src)
{
	mImagep = LLUI::getUIImageByID(src);
}

void LLStyle::setImage(const std::string& name)
{
	mImagep = LLUI::getUIImage(name);
}
<|endoftext|>


<commit_before>//===-- EmitFunctions.cpp - interface to insert instrumentation -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This inserts a global constant table with function pointers all along.
//
// NOTE: This pass is used by the reoptimizer only.
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CFG.h"
using namespace llvm;

namespace llvm {

namespace {
  enum Color{
    WHITE,
    GREY,
    BLACK
  };

  struct EmitFunctionTable : public ModulePass {
    bool runOnModule(Module &M);
  };

  RegisterOpt<EmitFunctionTable>
  X("emitfuncs", "Emit a function table for the reoptimizer");
}

static char doDFS(BasicBlock * node,std::map<BasicBlock *, Color > &color){
  color[node] = GREY;

  for(succ_iterator vl = succ_begin(node), ve = succ_end(node); vl != ve; ++vl){

    BasicBlock *BB = *vl;

    if(color[BB]!=GREY && color[BB]!=BLACK){
      if(!doDFS(BB, color)){
	return 0;
      }
    }

    //if has backedge
    else if(color[BB]==GREY)
      return 0;

  }

  color[node] = BLACK;
  return 1;
}

static char hasBackEdge(Function *F){
  std::map<BasicBlock *, Color > color;
  return doDFS(F->begin(), color);
}

// Per Module pass for inserting function table
bool EmitFunctionTable::runOnModule(Module &M){
  std::vector<const Type*> vType;

  std::vector<Constant *> vConsts;
  std::vector<Constant *> sBCons;

  unsigned int counter = 0;
  for(Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
    if (!MI->isExternal()) {
      vType.push_back(MI->getType());

      //std::cerr<<MI;

      vConsts.push_back(MI);
      sBCons.push_back(ConstantInt::get(Type::SByteTy, hasBackEdge(MI)));

      counter++;
    }

  StructType *sttype = StructType::get(vType);
  Constant *cstruct = ConstantStruct::get(sttype, vConsts);

  GlobalVariable *gb = new GlobalVariable(cstruct->getType(), true,
                                          GlobalValue::ExternalLinkage,
                                          cstruct, "llvmFunctionTable");
  M.getGlobalList().push_back(gb);

  Constant *constArray = ConstantArray::get(ArrayType::get(Type::SByteTy,
								sBCons.size()),
						 sBCons);

  GlobalVariable *funcArray = new GlobalVariable(constArray->getType(), true,
					      GlobalValue::ExternalLinkage,
					      constArray, "llvmSimpleFunction");

  M.getGlobalList().push_back(funcArray);

  ConstantInt *cnst = ConstantSInt::get(Type::IntTy, counter);
  GlobalVariable *fnCount = new GlobalVariable(Type::IntTy, true,
					       GlobalValue::ExternalLinkage,
					       cnst, "llvmFunctionCount");
  M.getGlobalList().push_back(fnCount);
  return true;  // Always modifies program
}

ModulePass *createEmitFunctionTablePass () {
  return new EmitFunctionTable();
}

} // end namespace llvm
<commit_msg>Explain what this pass does.<commit_after>//===-- EmitFunctions.cpp - interface to insert instrumentation -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This inserts into the input module three new global constants containing
// mapping information pertinent to the Reoptimizer's runtime library:
// 1) a structure containing a pointer to each function;
// 2) an array containing a boolean which is true iff the corresponding
//    function in 1) contains a back-edge branch suitable for the Reoptimizer's
//    first-level instrumentation;
// 3) an integer containing the number of entries in 1) and 2).
//
// NOTE: This pass is used by the reoptimizer only.
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CFG.h"
using namespace llvm;

namespace llvm {

namespace {
  enum Color{
    WHITE,
    GREY,
    BLACK
  };

  struct EmitFunctionTable : public ModulePass {
    bool runOnModule(Module &M);
  };

  RegisterOpt<EmitFunctionTable>
  X("emitfuncs", "Emit a function table for the reoptimizer");
}

static char doDFS(BasicBlock * node,std::map<BasicBlock *, Color > &color){
  color[node] = GREY;

  for(succ_iterator vl = succ_begin(node), ve = succ_end(node); vl != ve; ++vl){

    BasicBlock *BB = *vl;

    if(color[BB]!=GREY && color[BB]!=BLACK){
      if(!doDFS(BB, color)){
	return 0;
      }
    }

    //if has backedge
    else if(color[BB]==GREY)
      return 0;

  }

  color[node] = BLACK;
  return 1;
}

static char hasBackEdge(Function *F){
  std::map<BasicBlock *, Color > color;
  return doDFS(F->begin(), color);
}

// Per Module pass for inserting function table
bool EmitFunctionTable::runOnModule(Module &M){
  std::vector<const Type*> vType;

  std::vector<Constant *> vConsts;
  std::vector<Constant *> sBCons;

  unsigned int counter = 0;
  for(Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
    if (!MI->isExternal()) {
      vType.push_back(MI->getType());

      //std::cerr<<MI;

      vConsts.push_back(MI);
      sBCons.push_back(ConstantInt::get(Type::SByteTy, hasBackEdge(MI)));

      counter++;
    }

  StructType *sttype = StructType::get(vType);
  Constant *cstruct = ConstantStruct::get(sttype, vConsts);

  GlobalVariable *gb = new GlobalVariable(cstruct->getType(), true,
                                          GlobalValue::ExternalLinkage,
                                          cstruct, "llvmFunctionTable");
  M.getGlobalList().push_back(gb);

  Constant *constArray = ConstantArray::get(ArrayType::get(Type::SByteTy,
								sBCons.size()),
						 sBCons);

  GlobalVariable *funcArray = new GlobalVariable(constArray->getType(), true,
					      GlobalValue::ExternalLinkage,
					      constArray, "llvmSimpleFunction");

  M.getGlobalList().push_back(funcArray);

  ConstantInt *cnst = ConstantSInt::get(Type::IntTy, counter);
  GlobalVariable *fnCount = new GlobalVariable(Type::IntTy, true,
					       GlobalValue::ExternalLinkage,
					       cnst, "llvmFunctionCount");
  M.getGlobalList().push_back(fnCount);
  return true;  // Always modifies program
}

ModulePass *createEmitFunctionTablePass () {
  return new EmitFunctionTable();
}

} // end namespace llvm
<|endoftext|>


<commit_before>// @(#)root/mc:$Name:  $:$Id: TVirtualMC.cxx,v 1.1 2003/07/15 09:56:58 brun Exp $
// Authors: Ivana Hrivnacova, Rene Brun , Federico Carminati 13/04/2002

/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 **************************************************************************/

#include "TVirtualMC.h"

//______________________________________________________________________________
//   Virtual MC provides a virtual interface to Monte Carlo.
//   It enables the user to build a virtual Monte Carlo application
//   independent of any actual underlying Monte Carlo implementation itself.
//
//   A user will have to implement a class derived from the abstract
//   Monte Carlo application class, and provide functions like
//   ConstructGeometry(), BeginEvent(), FinishEvent(), ... .
//   The concrete Monte Carlo (Geant3, Geant4) is selected at run time -
//   when processing a ROOT macro where the concrete Monte Carlo is instantiated.
//______________________________________________________________________________

ClassImp(TVirtualMC)

TVirtualMC* TVirtualMC::fgMC=0;
TVirtualMC* gMC;

//_____________________________________________________________________________
TVirtualMC::TVirtualMC(const char *name, const char *title,
                       Bool_t isRootGeometrySupported)
  : TNamed(name,title),
    fStack(0),
    fDecayer(0),
    fRandom(0),
    fIsRootGeometrySupported(isRootGeometrySupported)
{
  //
  // Standard constructor
  //
  if(fgMC) {
    Warning("TVirtualMC","Cannot initialise twice MonteCarlo class");
  } else {
    fgMC=this;
    gMC=this;

    fApplication = TVirtualMCApplication::Instance();

    if (!fApplication) {
      Error("TVirtualMC", "No user MC application is defined.");
    }

    fRandom = gRandom;
  }
}

//_____________________________________________________________________________
TVirtualMC::TVirtualMC()
  : TNamed(),
    fApplication(0),
    fStack(0),
    fDecayer(0),
    fRandom(0),
    fIsRootGeometrySupported(kFALSE)
{
  //
  // Default constructor
  //
}

//_____________________________________________________________________________
TVirtualMC::~TVirtualMC()
{
  //
  // Destructor
  //
  fgMC=0;
  gMC=0;
}

//
// methods
//

//_____________________________________________________________________________
void TVirtualMC::SetStack(TVirtualMCStack* stack)
{
//
// Set particles stack.
//

  fStack = stack;
}

//_____________________________________________________________________________
void TVirtualMC::SetExternalDecayer(TVirtualMCDecayer* decayer)
{
//
// Set external decayer.
//

  fDecayer = decayer;
}

//_____________________________________________________________________________
void TVirtualMC::SetRandom(TRandom* random)
{
//
// Set random number generator.
//

   fRandom = random;
}

//_____________________________________________________________________________
Bool_t TVirtualMC::IsRootGeometrySupported() const
{
//
// Returns info whether Root geometry defined directly by TGeo
// is supported.
//
   return fIsRootGeometrySupported;
}

#include "Riostream.h"
//_____________________________________________________________________________
void  TVirtualMC::DefineParticles() {
//
  cerr << endl;
  cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
  cerr << "Warning in <TVirtualMC::DefineParticles>: This function is obsolete." << endl;
  cerr << "          Please remove the calls to it from your code" << endl;
  cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
  cerr << endl;
}
<commit_msg>In TVirtualMC::SetRandom set gRandom as well<commit_after>// @(#)root/mc:$Name:  $:$Id: TVirtualMC.cxx,v 1.2 2003/09/27 09:28:45 brun Exp $
// Authors: Ivana Hrivnacova, Rene Brun , Federico Carminati 13/04/2002

/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 **************************************************************************/

#include "TVirtualMC.h"

//______________________________________________________________________________
//   Virtual MC provides a virtual interface to Monte Carlo.
//   It enables the user to build a virtual Monte Carlo application
//   independent of any actual underlying Monte Carlo implementation itself.
//
//   A user will have to implement a class derived from the abstract
//   Monte Carlo application class, and provide functions like
//   ConstructGeometry(), BeginEvent(), FinishEvent(), ... .
//   The concrete Monte Carlo (Geant3, Geant4) is selected at run time -
//   when processing a ROOT macro where the concrete Monte Carlo is instantiated.
//______________________________________________________________________________

ClassImp(TVirtualMC)

TVirtualMC* TVirtualMC::fgMC=0;
TVirtualMC* gMC;

//_____________________________________________________________________________
TVirtualMC::TVirtualMC(const char *name, const char *title,
                       Bool_t isRootGeometrySupported)
  : TNamed(name,title),
    fStack(0),
    fDecayer(0),
    fRandom(0),
    fIsRootGeometrySupported(isRootGeometrySupported)
{
  //
  // Standard constructor
  //
  if(fgMC) {
    Warning("TVirtualMC","Cannot initialise twice MonteCarlo class");
  } else {
    fgMC=this;
    gMC=this;

    fApplication = TVirtualMCApplication::Instance();

    if (!fApplication) {
      Error("TVirtualMC", "No user MC application is defined.");
    }

    fRandom = gRandom;
  }
}

//_____________________________________________________________________________
TVirtualMC::TVirtualMC()
  : TNamed(),
    fApplication(0),
    fStack(0),
    fDecayer(0),
    fRandom(0),
    fIsRootGeometrySupported(kFALSE)
{
  //
  // Default constructor
  //
}

//_____________________________________________________________________________
TVirtualMC::~TVirtualMC()
{
  //
  // Destructor
  //
  fgMC=0;
  gMC=0;
}

//
// methods
//

//_____________________________________________________________________________
void TVirtualMC::SetStack(TVirtualMCStack* stack)
{
//
// Set particles stack.
//

  fStack = stack;
}

//_____________________________________________________________________________
void TVirtualMC::SetExternalDecayer(TVirtualMCDecayer* decayer)
{
//
// Set external decayer.
//

  fDecayer = decayer;
}

//_____________________________________________________________________________
void TVirtualMC::SetRandom(TRandom* random)
{
//
// Set random number generator.
//
   gRandom = random;
   fRandom = random;
}

//_____________________________________________________________________________
Bool_t TVirtualMC::IsRootGeometrySupported() const
{
//
// Returns info whether Root geometry defined directly by TGeo
// is supported.
//
   return fIsRootGeometrySupported;
}

#include "Riostream.h"
//_____________________________________________________________________________
void  TVirtualMC::DefineParticles() {
//
  cerr << endl;
  cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
  cerr << "Warning in <TVirtualMC::DefineParticles>: This function is obsolete." << endl;
  cerr << "          Please remove the calls to it from your code" << endl;
  cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
  cerr << endl;
}
<|endoftext|>


<commit_before>#line 2 "quanta/core/scripting/scripting.cpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <quanta/core/config.hpp>
#include <quanta/core/scripting/scripting.hpp>

#include <togo/core/error/assert.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/memory/memory.hpp>
#include <togo/core/string/string.hpp>

#include <cstring>

namespace quanta {

static void* alloc_func(void* ud, void* ptr, size_t osize, size_t nsize) {
	auto a = static_cast<Allocator*>(ud);
	if (nsize == 0) {
		a->deallocate(ptr);
		return nullptr;
	}

	void* new_ptr = a->allocate(nsize);
	// TODO: does Lua do resize blocks a lot? maybe this should be a nop
	// (togo allocators don't do reallocs)
	if (osize > 0) {
		std::memcpy(new_ptr, ptr, nsize);
	}
	a->deallocate(ptr);
	return new_ptr;
}

/// Create a new state with the given allocator.
///
/// allocator must exist as long as the state.
lua_State* lua::new_state(Allocator& allocator) {
	return lua_newstate(alloc_func, &allocator);
}

} // namespace quanta
<commit_msg>lib/core/scripting/scripting: added no-allocator new_state().¹<commit_after>#line 2 "quanta/core/scripting/scripting.cpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <quanta/core/config.hpp>
#include <quanta/core/scripting/scripting.hpp>

#include <togo/core/error/assert.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/memory/memory.hpp>
#include <togo/core/string/string.hpp>

#include <cstring>

namespace quanta {

static void* alloc_func(void* ud, void* ptr, size_t osize, size_t nsize) {
	auto a = static_cast<Allocator*>(ud);
	if (nsize == 0) {
		a->deallocate(ptr);
		return nullptr;
	}

	void* new_ptr = a->allocate(nsize);
	// TODO: does Lua do resize blocks a lot? maybe this should be a nop
	// (togo allocators don't do reallocs)
	if (osize > 0) {
		std::memcpy(new_ptr, ptr, nsize);
	}
	a->deallocate(ptr);
	return new_ptr;
}

/// Create a new state with the given allocator.
///
/// allocator must exist as long as the state.
lua_State* lua::new_state(Allocator& allocator) {
	return lua_newstate(alloc_func, &allocator);
}

/// Create a new state with Lua's allocator.
lua_State* lua::new_state() {
	return luaL_newstate();
}

} // namespace quanta
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <sstream>

#ifdef HAVE_BOOST
#include <boost/program_options.hpp>
#endif

#include "CmdSession.h"
#include <SmurffCpp/Predict/PredictSession.h>
#include <SmurffCpp/Sessions/SessionFactory.h>

#include <SmurffCpp/Configs/Config.h>
#include <SmurffCpp/Utils/Error.h>
#include <SmurffCpp/Version.h>
#include <SmurffCpp/IO/GenericIO.h>
#include <SmurffCpp/IO/MatrixIO.h>

#include <SmurffCpp/Utils/RootFile.h>
#include <SmurffCpp/Utils/StringUtils.h>

static const char *PREDICT_NAME = "predict";
static const char *HELP_NAME = "help";
static const char *PRIOR_NAME = "prior";
static const char *TEST_NAME = "test";
static const char *TRAIN_NAME = "train";
static const char *BURNIN_NAME = "burnin";
static const char *NSAMPLES_NAME = "nsamples";
static const char *NUM_LATENT_NAME = "num-latent";
static const char *NUM_THREADS_NAME = "num-threads";
static const char *SAVE_PREFIX_NAME = "save-prefix";
static const char *SAVE_EXTENSION_NAME = "save-extension";
static const char *SAVE_FREQ_NAME = "save-freq";
static const char *CHECKPOINT_FREQ_NAME = "checkpoint-freq";
static const char *THRESHOLD_NAME = "threshold";
static const char *VERBOSE_NAME = "verbose";
static const char *VERSION_NAME = "version";
static const char *SEED_NAME = "seed";
static const char *INI_NAME = "ini";
static const char *ROOT_NAME = "root";

using namespace smurff;

#ifdef HAVE_BOOST

namespace po = boost::program_options;

po::options_description get_desc()
{
    po::options_description general_desc("General parameters");
    general_desc.add_options()
	(VERSION_NAME, "print version info (and exit)")
	(HELP_NAME, "show this help information (and exit)")
	(INI_NAME, po::value<std::string>(), "read options from this .ini file")
	(NUM_THREADS_NAME, po::value<int>()->default_value(Config::NUM_THREADS_DEFAULT_VALUE), "number of threads (0 = default by OpenMP)")
	(VERBOSE_NAME, po::value<int>()->default_value(Config::VERBOSE_DEFAULT_VALUE), "verbosity of output (0, 1, 2 or 3)")
	(SEED_NAME, po::value<int>()->default_value(Config::RANDOM_SEED_DEFAULT_VALUE), "random number generator seed");

    po::options_description train_desc("Used during training");
    train_desc.add_options()
	(TRAIN_NAME, po::value<std::string>(), "train data file")
	(TEST_NAME, po::value<std::string>(), "test data")
	(PRIOR_NAME, po::value<std::vector<std::string>>()->multitoken(), "provide a prior-type for each dimension of train; prior-types:  <normal|normalone|spikeandslab|macau|macauone>")
	(BURNIN_NAME, po::value<int>()->default_value(Config::BURNIN_DEFAULT_VALUE), "number of samples to discard")
	(NSAMPLES_NAME, po::value<int>()->default_value(Config::NSAMPLES_DEFAULT_VALUE), "number of samples to collect")
	(NUM_LATENT_NAME, po::value<int>()->default_value(Config::NUM_LATENT_DEFAULT_VALUE), "number of latent dimensions")
	(THRESHOLD_NAME, po::value<double>()->default_value(Config::THRESHOLD_DEFAULT_VALUE), "threshold for binary classification and AUC calculation");

    po::options_description predict_desc("Used during prediction");
    predict_desc.add_options()
	(PREDICT_NAME, po::value<std::string>(), "sparse matrix with values to predict")
	(THRESHOLD_NAME, po::value<double>()->default_value(Config::THRESHOLD_DEFAULT_VALUE), "threshold for binary classification and AUC calculation");

    po::options_description save_desc("Storing models and predictions");
    save_desc.add_options()
	(ROOT_NAME, po::value<std::string>(), "restore session from root .ini file")
	(SAVE_PREFIX_NAME, po::value<std::string>()->default_value(Config::SAVE_PREFIX_DEFAULT_VALUE), "prefix for result files")
	(SAVE_EXTENSION_NAME, po::value<std::string>()->default_value(Config::SAVE_EXTENSION_DEFAULT_VALUE), "extension for result files (.csv or .ddm)")
	(SAVE_FREQ_NAME, po::value<int>()->default_value(Config::SAVE_FREQ_DEFAULT_VALUE), "save every n iterations (0 == never, -1 == final model)")
	(CHECKPOINT_FREQ_NAME, po::value<int>()->default_value(Config::CHECKPOINT_FREQ_DEFAULT_VALUE), "save state every n seconds, only one checkpointing state is kept");

    po::options_description desc("SMURFF: Scalable Matrix Factorization Framework\n\thttp://github.com/ExaScience/smurff");
    desc.add(general_desc);
    desc.add(train_desc);
    desc.add(predict_desc);
    desc.add(save_desc);

    return desc;
}

struct ConfigFiller
{
    const po::variables_map &vm;
    Config &config;

    template <typename T, void (Config::*Func)(T)>
    void set(std::string name)
    {
        if (vm.count(name) && !vm[name].defaulted())
            (config.*Func)(vm[name].as<T>());
    }

    template <void (Config::*Func)(std::shared_ptr<TensorConfig>)>
    void set_tensor(std::string name, bool set_noise)
    {
        if (vm.count(name) && !vm[name].defaulted())
        {
            auto tensor_config = generic_io::read_data_config(vm[name].as<std::string>(), true);
            tensor_config->setNoiseConfig(NoiseConfig(NoiseConfig::NOISE_TYPE_DEFAULT_VALUE));
            (this->config.*Func)(tensor_config);
        }
    }

    void set_priors(std::string name)
    {
        if (vm.count(name) && !vm[name].defaulted())
            config.setPriorTypes(vm[name].as<std::vector<std::string>>());
    }
};

// variables_map -> Config
Config
fill_config(const po::variables_map &vm)
{
    Config config;
    ConfigFiller filler = {vm, config};

    //restore session from root file (command line arguments are already stored in file)
    if (vm.count(ROOT_NAME))
    {
        //restore config from root file
        std::string root_name = vm[ROOT_NAME].as<std::string>();
        config.setRootName(root_name);

        if (!vm.count(PREDICT_NAME))
            RootFile(root_name).restoreConfig(config);
    }

    //restore ini file if it was specified
    if (vm.count(INI_NAME))
    {
        auto ini_file = vm[INI_NAME].as<std::string>();
        bool success = config.restore(ini_file);
        THROWERROR_ASSERT_MSG(success, "Could not load ini file '" + ini_file + "'");
        config.setIniName(ini_file);
    }

    filler.set_tensor<&Config::setPredict>(PREDICT_NAME, false);
    filler.set_tensor<&Config::setTest>(TEST_NAME, false);
    filler.set_tensor<&Config::setTrain>(TRAIN_NAME, true);

    filler.set_priors(PRIOR_NAME);

    filler.set<double,      &Config::setThreshold>(THRESHOLD_NAME);
    filler.set<int,         &Config::setBurnin>(BURNIN_NAME);
    filler.set<int,         &Config::setNSamples>(NSAMPLES_NAME);
    filler.set<int,         &Config::setNumLatent>(NUM_LATENT_NAME);
    filler.set<int,         &Config::setNumThreads>(NUM_THREADS_NAME);
    filler.set<std::string, &Config::setSavePrefix>(SAVE_PREFIX_NAME);
    filler.set<std::string, &Config::setSaveExtension>(SAVE_EXTENSION_NAME);
    filler.set<int,         &Config::setSaveFreq>(SAVE_FREQ_NAME);
    filler.set<int,         &Config::setCheckpointFreq>(CHECKPOINT_FREQ_NAME);
    filler.set<double,      &Config::setThreshold>(THRESHOLD_NAME);
    filler.set<int,         &Config::setVerbose>(VERBOSE_NAME);
    filler.set<int,         &Config::setRandomSeed>(SEED_NAME);

    return config;
}

// argc/argv -> variables_map -> Config
Config smurff::parse_options(int argc, char *argv[])
{
    po::variables_map vm;

    try
    {
        po::options_description desc = get_desc();

        if (argc < 2)
        {
            std::cout << desc << std::endl;
            return Config();
        }

        po::command_line_parser parser{argc, argv};
        parser.options(desc);

        po::parsed_options parsed_options = parser.run();

        store(parsed_options, vm);
        notify(vm);

        if (vm.count(HELP_NAME))
        {
            std::cout << desc << std::endl;
            return Config();
        }

        if (vm.count(VERSION_NAME))
        {
            std::cout << "SMURFF " << smurff::SMURFF_VERSION << std::endl;
            return Config();
        }
    }
    catch (const po::error &ex)
    {
        std::cerr << "Failed to parse command line arguments: " << std::endl;
        std::cerr << ex.what() << std::endl;
        throw(ex);
    }
    catch (std::runtime_error &ex)
    {
        std::cerr << "Failed to parse command line arguments: " << std::endl;
        std::cerr << ex.what() << std::endl;
        throw(ex);
    }

    const std::vector<std::string> train_only_options = {
        TRAIN_NAME, TEST_NAME, PRIOR_NAME, BURNIN_NAME, NSAMPLES_NAME, NUM_LATENT_NAME};

    //-- prediction only
    if (vm.count(PREDICT_NAME))
    {
        if (!vm.count(ROOT_NAME))
            THROWERROR("Need --root option in predict mode");

        for (auto name : train_only_options)
        {
            if (vm.count(name) && !vm[name].defaulted())
                THROWERROR("You're not allowed to mix train options (--" + name + ") with --predict");
        }
    }

    return fill_config(vm);
}

#else // no BOOST

// argc/argv --> Config
Config smurff::parse_options(int argc, char *argv[])
{
    auto usage = []() {
        std::cerr << "Usage:\n\tsmurff --[ini|root] <ini_file.ini>\n\n"
                  << "(Limited smurff compiled w/o boost program options)" << std::endl;
        exit(0);
    };

    if (argc != 3) usage();

    Config config;

    //restore session from root file (command line arguments are already stored in file)
    if (std::string(argv[1]) == "--" + std::string(ROOT_NAME))
    {
        std::string root_name(argv[2]);
        RootFile(root_name).restoreConfig(config);
        config.setRootName(root_name);
     }

    //create new session from config (passing command line arguments)
    else if (std::string(argv[1]) == "--" + std::string(INI_NAME))
    {
        std::string ini_file(argv[2]);
        bool success = config.restore(ini_file);
        THROWERROR_ASSERT_MSG(success, "Could not load ini file '" + ini_file + "'");
        config.setIniName(ini_file);
    }
    else
    {
        usage();
    }

    return config;
}
#endif

//create cmd session
//parses args with setFromArgs, then internally calls setFromConfig (to validate, save, set config)
std::shared_ptr<ISession> smurff::create_cmd_session(int argc, char **argv)
{
    std::shared_ptr<ISession> session;

    auto config = parse_options(argc, argv);
    if (config.isActionTrain())
        session = SessionFactory::create_session(config);
    else if (config.isActionPredict())
        session = std::make_shared<PredictSession>(config);
    else
        exit(0);

    return session;
}
<commit_msg>move unused const chars inside ifdef<commit_after>#include <string>
#include <iostream>
#include <sstream>

#ifdef HAVE_BOOST
#include <boost/program_options.hpp>
#endif

#include "CmdSession.h"
#include <SmurffCpp/Predict/PredictSession.h>
#include <SmurffCpp/Sessions/SessionFactory.h>

#include <SmurffCpp/Configs/Config.h>
#include <SmurffCpp/Utils/Error.h>
#include <SmurffCpp/Version.h>
#include <SmurffCpp/IO/GenericIO.h>
#include <SmurffCpp/IO/MatrixIO.h>

#include <SmurffCpp/Utils/RootFile.h>
#include <SmurffCpp/Utils/StringUtils.h>

using namespace smurff;

static const char *INI_NAME = "ini";
static const char *ROOT_NAME = "root";

#ifdef HAVE_BOOST

static const char *PREDICT_NAME = "predict";
static const char *HELP_NAME = "help";
static const char *PRIOR_NAME = "prior";
static const char *TEST_NAME = "test";
static const char *TRAIN_NAME = "train";
static const char *BURNIN_NAME = "burnin";
static const char *NSAMPLES_NAME = "nsamples";
static const char *NUM_LATENT_NAME = "num-latent";
static const char *NUM_THREADS_NAME = "num-threads";
static const char *SAVE_PREFIX_NAME = "save-prefix";
static const char *SAVE_EXTENSION_NAME = "save-extension";
static const char *SAVE_FREQ_NAME = "save-freq";
static const char *CHECKPOINT_FREQ_NAME = "checkpoint-freq";
static const char *THRESHOLD_NAME = "threshold";
static const char *VERBOSE_NAME = "verbose";
static const char *VERSION_NAME = "version";
static const char *SEED_NAME = "seed";

namespace po = boost::program_options;

po::options_description get_desc()
{
    po::options_description general_desc("General parameters");
    general_desc.add_options()
	(VERSION_NAME, "print version info (and exit)")
	(HELP_NAME, "show this help information (and exit)")
	(INI_NAME, po::value<std::string>(), "read options from this .ini file")
	(NUM_THREADS_NAME, po::value<int>()->default_value(Config::NUM_THREADS_DEFAULT_VALUE), "number of threads (0 = default by OpenMP)")
	(VERBOSE_NAME, po::value<int>()->default_value(Config::VERBOSE_DEFAULT_VALUE), "verbosity of output (0, 1, 2 or 3)")
	(SEED_NAME, po::value<int>()->default_value(Config::RANDOM_SEED_DEFAULT_VALUE), "random number generator seed");

    po::options_description train_desc("Used during training");
    train_desc.add_options()
	(TRAIN_NAME, po::value<std::string>(), "train data file")
	(TEST_NAME, po::value<std::string>(), "test data")
	(PRIOR_NAME, po::value<std::vector<std::string>>()->multitoken(), "provide a prior-type for each dimension of train; prior-types:  <normal|normalone|spikeandslab|macau|macauone>")
	(BURNIN_NAME, po::value<int>()->default_value(Config::BURNIN_DEFAULT_VALUE), "number of samples to discard")
	(NSAMPLES_NAME, po::value<int>()->default_value(Config::NSAMPLES_DEFAULT_VALUE), "number of samples to collect")
	(NUM_LATENT_NAME, po::value<int>()->default_value(Config::NUM_LATENT_DEFAULT_VALUE), "number of latent dimensions")
	(THRESHOLD_NAME, po::value<double>()->default_value(Config::THRESHOLD_DEFAULT_VALUE), "threshold for binary classification and AUC calculation");

    po::options_description predict_desc("Used during prediction");
    predict_desc.add_options()
	(PREDICT_NAME, po::value<std::string>(), "sparse matrix with values to predict")
	(THRESHOLD_NAME, po::value<double>()->default_value(Config::THRESHOLD_DEFAULT_VALUE), "threshold for binary classification and AUC calculation");

    po::options_description save_desc("Storing models and predictions");
    save_desc.add_options()
	(ROOT_NAME, po::value<std::string>(), "restore session from root .ini file")
	(SAVE_PREFIX_NAME, po::value<std::string>()->default_value(Config::SAVE_PREFIX_DEFAULT_VALUE), "prefix for result files")
	(SAVE_EXTENSION_NAME, po::value<std::string>()->default_value(Config::SAVE_EXTENSION_DEFAULT_VALUE), "extension for result files (.csv or .ddm)")
	(SAVE_FREQ_NAME, po::value<int>()->default_value(Config::SAVE_FREQ_DEFAULT_VALUE), "save every n iterations (0 == never, -1 == final model)")
	(CHECKPOINT_FREQ_NAME, po::value<int>()->default_value(Config::CHECKPOINT_FREQ_DEFAULT_VALUE), "save state every n seconds, only one checkpointing state is kept");

    po::options_description desc("SMURFF: Scalable Matrix Factorization Framework\n\thttp://github.com/ExaScience/smurff");
    desc.add(general_desc);
    desc.add(train_desc);
    desc.add(predict_desc);
    desc.add(save_desc);

    return desc;
}

struct ConfigFiller
{
    const po::variables_map &vm;
    Config &config;

    template <typename T, void (Config::*Func)(T)>
    void set(std::string name)
    {
        if (vm.count(name) && !vm[name].defaulted())
            (config.*Func)(vm[name].as<T>());
    }

    template <void (Config::*Func)(std::shared_ptr<TensorConfig>)>
    void set_tensor(std::string name, bool set_noise)
    {
        if (vm.count(name) && !vm[name].defaulted())
        {
            auto tensor_config = generic_io::read_data_config(vm[name].as<std::string>(), true);
            tensor_config->setNoiseConfig(NoiseConfig(NoiseConfig::NOISE_TYPE_DEFAULT_VALUE));
            (this->config.*Func)(tensor_config);
        }
    }

    void set_priors(std::string name)
    {
        if (vm.count(name) && !vm[name].defaulted())
            config.setPriorTypes(vm[name].as<std::vector<std::string>>());
    }
};

// variables_map -> Config
Config
fill_config(const po::variables_map &vm)
{
    Config config;
    ConfigFiller filler = {vm, config};

    //restore session from root file (command line arguments are already stored in file)
    if (vm.count(ROOT_NAME))
    {
        //restore config from root file
        std::string root_name = vm[ROOT_NAME].as<std::string>();
        config.setRootName(root_name);

        if (!vm.count(PREDICT_NAME))
            RootFile(root_name).restoreConfig(config);
    }

    //restore ini file if it was specified
    if (vm.count(INI_NAME))
    {
        auto ini_file = vm[INI_NAME].as<std::string>();
        bool success = config.restore(ini_file);
        THROWERROR_ASSERT_MSG(success, "Could not load ini file '" + ini_file + "'");
        config.setIniName(ini_file);
    }

    filler.set_tensor<&Config::setPredict>(PREDICT_NAME, false);
    filler.set_tensor<&Config::setTest>(TEST_NAME, false);
    filler.set_tensor<&Config::setTrain>(TRAIN_NAME, true);

    filler.set_priors(PRIOR_NAME);

    filler.set<double,      &Config::setThreshold>(THRESHOLD_NAME);
    filler.set<int,         &Config::setBurnin>(BURNIN_NAME);
    filler.set<int,         &Config::setNSamples>(NSAMPLES_NAME);
    filler.set<int,         &Config::setNumLatent>(NUM_LATENT_NAME);
    filler.set<int,         &Config::setNumThreads>(NUM_THREADS_NAME);
    filler.set<std::string, &Config::setSavePrefix>(SAVE_PREFIX_NAME);
    filler.set<std::string, &Config::setSaveExtension>(SAVE_EXTENSION_NAME);
    filler.set<int,         &Config::setSaveFreq>(SAVE_FREQ_NAME);
    filler.set<int,         &Config::setCheckpointFreq>(CHECKPOINT_FREQ_NAME);
    filler.set<double,      &Config::setThreshold>(THRESHOLD_NAME);
    filler.set<int,         &Config::setVerbose>(VERBOSE_NAME);
    filler.set<int,         &Config::setRandomSeed>(SEED_NAME);

    return config;
}

// argc/argv -> variables_map -> Config
Config smurff::parse_options(int argc, char *argv[])
{
    po::variables_map vm;

    try
    {
        po::options_description desc = get_desc();

        if (argc < 2)
        {
            std::cout << desc << std::endl;
            return Config();
        }

        po::command_line_parser parser{argc, argv};
        parser.options(desc);

        po::parsed_options parsed_options = parser.run();

        store(parsed_options, vm);
        notify(vm);

        if (vm.count(HELP_NAME))
        {
            std::cout << desc << std::endl;
            return Config();
        }

        if (vm.count(VERSION_NAME))
        {
            std::cout << "SMURFF " << smurff::SMURFF_VERSION << std::endl;
            return Config();
        }
    }
    catch (const po::error &ex)
    {
        std::cerr << "Failed to parse command line arguments: " << std::endl;
        std::cerr << ex.what() << std::endl;
        throw(ex);
    }
    catch (std::runtime_error &ex)
    {
        std::cerr << "Failed to parse command line arguments: " << std::endl;
        std::cerr << ex.what() << std::endl;
        throw(ex);
    }

    const std::vector<std::string> train_only_options = {
        TRAIN_NAME, TEST_NAME, PRIOR_NAME, BURNIN_NAME, NSAMPLES_NAME, NUM_LATENT_NAME};

    //-- prediction only
    if (vm.count(PREDICT_NAME))
    {
        if (!vm.count(ROOT_NAME))
            THROWERROR("Need --root option in predict mode");

        for (auto name : train_only_options)
        {
            if (vm.count(name) && !vm[name].defaulted())
                THROWERROR("You're not allowed to mix train options (--" + name + ") with --predict");
        }
    }

    return fill_config(vm);
}

#else // no BOOST

// argc/argv --> Config
Config smurff::parse_options(int argc, char *argv[])
{
    auto usage = []() {
        std::cerr << "Usage:\n\tsmurff --[ini|root] <ini_file.ini>\n\n"
                  << "(Limited smurff compiled w/o boost program options)" << std::endl;
        exit(0);
    };

    if (argc != 3) usage();

    Config config;

    //restore session from root file (command line arguments are already stored in file)
    if (std::string(argv[1]) == "--" + std::string(ROOT_NAME))
    {
        std::string root_name(argv[2]);
        RootFile(root_name).restoreConfig(config);
        config.setRootName(root_name);
     }

    //create new session from config (passing command line arguments)
    else if (std::string(argv[1]) == "--" + std::string(INI_NAME))
    {
        std::string ini_file(argv[2]);
        bool success = config.restore(ini_file);
        THROWERROR_ASSERT_MSG(success, "Could not load ini file '" + ini_file + "'");
        config.setIniName(ini_file);
    }
    else
    {
        usage();
    }

    return config;
}
#endif

//create cmd session
//parses args with setFromArgs, then internally calls setFromConfig (to validate, save, set config)
std::shared_ptr<ISession> smurff::create_cmd_session(int argc, char **argv)
{
    std::shared_ptr<ISession> session;

    auto config = parse_options(argc, argv);
    if (config.isActionTrain())
        session = SessionFactory::create_session(config);
    else if (config.isActionPredict())
        session = std::make_shared<PredictSession>(config);
    else
        exit(0);

    return session;
}
<|endoftext|>