<commit_before>#include "addressbookpage.h"
#include "ui_addressbookpage.h"

#include "addresstablemodel.h"
#include "optionsmodel.h"
#include "bitcoingui.h"
#include "editaddressdialog.h"
#include "csvmodelwriter.h"
#include "guiutil.h"

#ifdef USE_QRCODE
#include "qrcodedialog.h"
#endif

#include <QSortFilterProxyModel>
#include <QClipboard>
#include <QMessageBox>
#include <QMenu>

AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AddressBookPage),
    model(0),
    optionsModel(0),
    mode(mode),
    tab(tab)
{
    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->newAddressButton->setIcon(QIcon());
    ui->copyToClipboard->setIcon(QIcon());
    ui->deleteButton->setIcon(QIcon());
#endif

#ifndef USE_QRCODE
    ui->showQRCode->setVisible(false);
#endif

    switch(mode)
    {
    case ForSending:
        connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
        ui->tableView->setFocus();
        break;
    case ForEditing:
        ui->buttonBox->setVisible(false);
        break;
    }
    switch(tab)
    {
    case SendingTab:
        ui->labelExplanation->setVisible(false);
        ui->deleteButton->setVisible(true);
        ui->signMessage->setVisible(false);
        break;
    case ReceivingTab:
        ui->deleteButton->setVisible(false);
        ui->signMessage->setVisible(true);
        break;
    }

    // Context menu actions
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *copyAddressAction = new QAction(ui->copyToClipboard->text(), this);
    QAction *editAction = new QAction(tr("&Edit"), this);

/*	#ifdef USE_QRCODE
    // Context menu actions
    QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this);
	#endif
*/
    QAction *signMessageAction = new QAction(ui->signMessage->text(), this);
    QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this);
    deleteAction = new QAction(ui->deleteButton->text(), this);

    // Build context menu
    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    if(tab == SendingTab)
        contextMenu->addAction(deleteAction);
    contextMenu->addSeparator();
/*
	#ifdef USE_QRCODE
       // Build context menu
    contextMenu->addAction(showQRCodeAction);
	#endif
*/

    if(tab == ReceivingTab)
        contextMenu->addAction(signMessageAction);
    else if(tab == SendingTab)
        contextMenu->addAction(verifyMessageAction);

    // Connect signals for context menu actions
    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
    connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
    connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked()));

	#ifdef USE_QRCODE
      	addQrCodeGuiElements();
	#endif

    connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked()));
    connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked()));

    connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    // Pass through accept action from button box
    connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
}

void AddressBookPage::addQrCodeGuiElements()
{
	// Context menu actions
	QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this);
	// Build context menu
	contextMenu->addAction(showQRCodeAction);
	// Connect signals for context menu actions
	connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked()));
}

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

void AddressBookPage::setModel(AddressTableModel *model)
{
    this->model = model;
    if(!model)
        return;

    proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);
    proxyModel->setDynamicSortFilter(true);
    proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
    proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
    switch(tab)
    {
    case ReceivingTab:
        // Receive filter
        proxyModel->setFilterRole(AddressTableModel::TypeRole);
        proxyModel->setFilterFixedString(AddressTableModel::Receive);
        break;
    case SendingTab:
        // Send filter
        proxyModel->setFilterRole(AddressTableModel::TypeRole);
        proxyModel->setFilterFixedString(AddressTableModel::Send);
        break;
    }
    ui->tableView->setModel(proxyModel);
    ui->tableView->sortByColumn(0, Qt::AscendingOrder);

    // Set column widths
    ui->tableView->horizontalHeader()->resizeSection(
            AddressTableModel::Address, 320);
    ui->tableView->horizontalHeader()->setResizeMode(
            AddressTableModel::Label, QHeaderView::Stretch);

    connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(selectionChanged()));

    // Select row for newly created address
    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(selectNewAddress(QModelIndex,int,int)));

    selectionChanged();
}

void AddressBookPage::setOptionsModel(OptionsModel *optionsModel)
{
    this->optionsModel = optionsModel;
}

void AddressBookPage::on_copyToClipboard_clicked()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
}

void AddressBookPage::onCopyLabelAction()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Label);
}

void AddressBookPage::onEditAction()
{
    if(!ui->tableView->selectionModel())
        return;
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if(indexes.isEmpty())
        return;

    EditAddressDialog dlg(
            tab == SendingTab ?
            EditAddressDialog::EditSendingAddress :
            EditAddressDialog::EditReceivingAddress);
    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();
}

void AddressBookPage::on_signMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit signMessage(addr);
}

void AddressBookPage::on_verifyMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit verifyMessage(addr);
}

void AddressBookPage::on_newAddressButton_clicked()
{
    if(!model)
        return;
    EditAddressDialog dlg(
            tab == SendingTab ?
            EditAddressDialog::NewSendingAddress :
            EditAddressDialog::NewReceivingAddress, this);
    dlg.setModel(model);
    if(dlg.exec())
    {
        newAddressToSelect = dlg.getAddress();
    }
}

void AddressBookPage::on_deleteButton_clicked()
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;
    QModelIndexList indexes = table->selectionModel()->selectedRows();
    if(!indexes.isEmpty())
    {
        table->model()->removeRow(indexes.at(0).row());
    }
}

void AddressBookPage::selectionChanged()
{
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;

    if(table->selectionModel()->hasSelection())
    {
        switch(tab)
        {
        case SendingTab:
            // In sending tab, allow deletion of selection
            ui->deleteButton->setEnabled(true);
            ui->deleteButton->setVisible(true);
            deleteAction->setEnabled(true);
            ui->signMessage->setEnabled(false);
            ui->signMessage->setVisible(false);
            ui->verifyMessage->setEnabled(true);
            ui->verifyMessage->setVisible(true);
            break;
        case ReceivingTab:
            // Deleting receiving addresses, however, is not allowed
            ui->deleteButton->setEnabled(false);
            ui->deleteButton->setVisible(false);
            deleteAction->setEnabled(false);
            ui->signMessage->setEnabled(true);
            ui->signMessage->setVisible(true);
            ui->verifyMessage->setEnabled(false);
            ui->verifyMessage->setVisible(false);
            break;
        }
        ui->copyToClipboard->setEnabled(true);
        ui->showQRCode->setEnabled(true);
    }
    else
    {
        ui->deleteButton->setEnabled(false);
        ui->showQRCode->setEnabled(false);
        ui->copyToClipboard->setEnabled(false);
        ui->signMessage->setEnabled(false);
        ui->verifyMessage->setEnabled(false);
    }
}

void AddressBookPage::done(int retval)
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel() || !table->model())
        return;
    // When this is a tab/widget and not a model dialog, ignore "done"
    if(mode == ForEditing)
        return;

    // Figure out which address was selected, and return it
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QVariant address = table->model()->data(index);
        returnValue = address.toString();
    }

    if(returnValue.isEmpty())
    {
        // If no address entry selected, return rejected
        retval = Rejected;
    }

    QDialog::done(retval);
}

void AddressBookPage::exportClicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(
            this,
            tr("Export Address Book Data"), QString(),
            tr("Comma separated file (*.csv)"));

    if (filename.isNull()) return;

    CSVModelWriter writer(filename);

    // name, column, role
    writer.setModel(proxyModel);
    writer.addColumn("Label", AddressTableModel::Label, Qt::EditRole);
    writer.addColumn("Address", AddressTableModel::Address, Qt::EditRole);

    if(!writer.write())
    {
        QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
                              QMessageBox::Abort, QMessageBox::Abort);
    }
}

void AddressBookPage::on_showQRCode_clicked()
{
#ifdef USE_QRCODE
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString();

        QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this);
        if(optionsModel)
            dialog->setModel(optionsModel);
        dialog->setAttribute(Qt::WA_DeleteOnClose);
        dialog->show();
    }
#endif
}

void AddressBookPage::contextualMenu(const QPoint &point)
{
    QModelIndex index = ui->tableView->indexAt(point);
    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int end)
{
    QModelIndex idx = proxyModel->mapFromSource(model->index(begin, AddressTableModel::Address, parent));
    if(idx.isValid() && (idx.data(Qt::EditRole).toString() == newAddressToSelect))
    {
        // Select row of newly created address, once
        ui->tableView->setFocus();
        ui->tableView->selectRow(idx.row());
        newAddressToSelect.clear();
    }
}
<commit_msg>cleaned up files<commit_after>#include "addressbookpage.h"
#include "ui_addressbookpage.h"

#include "addresstablemodel.h"
#include "optionsmodel.h"
#include "bitcoingui.h"
#include "editaddressdialog.h"
#include "csvmodelwriter.h"
#include "guiutil.h"

#ifdef USE_QRCODE
	#include "qrcodedialog.h"
#endif

#include <QSortFilterProxyModel>
#include <QClipboard>
#include <QMessageBox>
#include <QMenu>

AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AddressBookPage),
    model(0),
    optionsModel(0),
    mode(mode),
    tab(tab)
{
    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->newAddressButton->setIcon(QIcon());
    ui->copyToClipboard->setIcon(QIcon());
    ui->deleteButton->setIcon(QIcon());
#endif

#ifndef USE_QRCODE
    ui->showQRCode->setVisible(false);
#endif

    switch(mode)
    {
    case ForSending:
        connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
        ui->tableView->setFocus();
        break;
    case ForEditing:
        ui->buttonBox->setVisible(false);
        break;
    }
    switch(tab)
    {
    case SendingTab:
        ui->labelExplanation->setVisible(false);
        ui->deleteButton->setVisible(true);
        ui->signMessage->setVisible(false);
        break;
    case ReceivingTab:
        ui->deleteButton->setVisible(false);
        ui->signMessage->setVisible(true);
        break;
    }

    // Context menu actions
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *copyAddressAction = new QAction(ui->copyToClipboard->text(), this);
    QAction *editAction = new QAction(tr("&Edit"), this);

    QAction *signMessageAction = new QAction(ui->signMessage->text(), this);
    QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this);
    deleteAction = new QAction(ui->deleteButton->text(), this);

    // Build context menu
    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    if(tab == SendingTab)
        contextMenu->addAction(deleteAction);
    contextMenu->addSeparator();

    if(tab == ReceivingTab)
        contextMenu->addAction(signMessageAction);
    else if(tab == SendingTab)
        contextMenu->addAction(verifyMessageAction);

    // Connect signals for context menu actions
    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
    connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
    connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked()));

	#ifdef USE_QRCODE
      	addQrCodeGuiElements();
	#endif

    connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked()));
    connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked()));

    connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    // Pass through accept action from button box
    connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
}

void AddressBookPage::addQrCodeGuiElements()
{
	// Context menu actions
	QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this);
	// Build context menu
	contextMenu->addAction(showQRCodeAction);
	// Connect signals for context menu actions
	connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked()));
}

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

void AddressBookPage::setModel(AddressTableModel *model)
{
    this->model = model;
    if(!model)
        return;

    proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);
    proxyModel->setDynamicSortFilter(true);
    proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
    proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
    switch(tab)
    {
    case ReceivingTab:
        // Receive filter
        proxyModel->setFilterRole(AddressTableModel::TypeRole);
        proxyModel->setFilterFixedString(AddressTableModel::Receive);
        break;
    case SendingTab:
        // Send filter
        proxyModel->setFilterRole(AddressTableModel::TypeRole);
        proxyModel->setFilterFixedString(AddressTableModel::Send);
        break;
    }
    ui->tableView->setModel(proxyModel);
    ui->tableView->sortByColumn(0, Qt::AscendingOrder);

    // Set column widths
    ui->tableView->horizontalHeader()->resizeSection(
            AddressTableModel::Address, 320);
    ui->tableView->horizontalHeader()->setResizeMode(
            AddressTableModel::Label, QHeaderView::Stretch);

    connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(selectionChanged()));

    // Select row for newly created address
    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(selectNewAddress(QModelIndex,int,int)));

    selectionChanged();
}

void AddressBookPage::setOptionsModel(OptionsModel *optionsModel)
{
    this->optionsModel = optionsModel;
}

void AddressBookPage::on_copyToClipboard_clicked()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
}

void AddressBookPage::onCopyLabelAction()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Label);
}

void AddressBookPage::onEditAction()
{
    if(!ui->tableView->selectionModel())
        return;
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if(indexes.isEmpty())
        return;

    EditAddressDialog dlg(
            tab == SendingTab ?
            EditAddressDialog::EditSendingAddress :
            EditAddressDialog::EditReceivingAddress);
    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();
}

void AddressBookPage::on_signMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit signMessage(addr);
}

void AddressBookPage::on_verifyMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit verifyMessage(addr);
}

void AddressBookPage::on_newAddressButton_clicked()
{
    if(!model)
        return;
    EditAddressDialog dlg(
            tab == SendingTab ?
            EditAddressDialog::NewSendingAddress :
            EditAddressDialog::NewReceivingAddress, this);
    dlg.setModel(model);
    if(dlg.exec())
    {
        newAddressToSelect = dlg.getAddress();
    }
}

void AddressBookPage::on_deleteButton_clicked()
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;
    QModelIndexList indexes = table->selectionModel()->selectedRows();
    if(!indexes.isEmpty())
    {
        table->model()->removeRow(indexes.at(0).row());
    }
}

void AddressBookPage::selectionChanged()
{
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;

    if(table->selectionModel()->hasSelection())
    {
        switch(tab)
        {
        case SendingTab:
            // In sending tab, allow deletion of selection
            ui->deleteButton->setEnabled(true);
            ui->deleteButton->setVisible(true);
            deleteAction->setEnabled(true);
            ui->signMessage->setEnabled(false);
            ui->signMessage->setVisible(false);
            ui->verifyMessage->setEnabled(true);
            ui->verifyMessage->setVisible(true);
            break;
        case ReceivingTab:
            // Deleting receiving addresses, however, is not allowed
            ui->deleteButton->setEnabled(false);
            ui->deleteButton->setVisible(false);
            deleteAction->setEnabled(false);
            ui->signMessage->setEnabled(true);
            ui->signMessage->setVisible(true);
            ui->verifyMessage->setEnabled(false);
            ui->verifyMessage->setVisible(false);
            break;
        }
        ui->copyToClipboard->setEnabled(true);
        ui->showQRCode->setEnabled(true);
    }
    else
    {
        ui->deleteButton->setEnabled(false);
        ui->showQRCode->setEnabled(false);
        ui->copyToClipboard->setEnabled(false);
        ui->signMessage->setEnabled(false);
        ui->verifyMessage->setEnabled(false);
    }
}

void AddressBookPage::done(int retval)
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel() || !table->model())
        return;
    // When this is a tab/widget and not a model dialog, ignore "done"
    if(mode == ForEditing)
        return;

    // Figure out which address was selected, and return it
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QVariant address = table->model()->data(index);
        returnValue = address.toString();
    }

    if(returnValue.isEmpty())
    {
        // If no address entry selected, return rejected
        retval = Rejected;
    }

    QDialog::done(retval);
}

void AddressBookPage::exportClicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(
            this,
            tr("Export Address Book Data"), QString(),
            tr("Comma separated file (*.csv)"));

    if (filename.isNull()) return;

    CSVModelWriter writer(filename);

    // name, column, role
    writer.setModel(proxyModel);
    writer.addColumn("Label", AddressTableModel::Label, Qt::EditRole);
    writer.addColumn("Address", AddressTableModel::Address, Qt::EditRole);

    if(!writer.write())
    {
        QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
                              QMessageBox::Abort, QMessageBox::Abort);
    }
}

void AddressBookPage::on_showQRCode_clicked()
{
#ifdef USE_QRCODE
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString();

        QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this);
        if(optionsModel)
            dialog->setModel(optionsModel);
        dialog->setAttribute(Qt::WA_DeleteOnClose);
        dialog->show();
    }
#endif
}

void AddressBookPage::contextualMenu(const QPoint &point)
{
    QModelIndex index = ui->tableView->indexAt(point);
    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int end)
{
    QModelIndex idx = proxyModel->mapFromSource(model->index(begin, AddressTableModel::Address, parent));
    if(idx.isValid() && (idx.data(Qt::EditRole).toString() == newAddressToSelect))
    {
        // Select row of newly created address, once
        ui->tableView->setFocus();
        ui->tableView->selectRow(idx.row());
        newAddressToSelect.clear();
    }
}
<|endoftext|>


<commit_before>// MainGame.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "src\Tool\Init.h"
#include "src\tilemap.h"

ALLEGRO_DISPLAY     *display = nullptr;
ALLEGRO_EVENT_QUEUE *queue = nullptr;
ALLEGRO_TIMER       *timer = nullptr;
ALLEGRO_FONT        *textFont = nullptr;

InitData  applicationConfig;
StyleData styleConfig;

bool Init()
{
    if (LoadConfigurationData(applicationConfig, styleConfig) == false)
        return false;

    al_init();

    if (applicationConfig.bfullscreen == true)
    {
        al_set_new_display_flags(ALLEGRO_FULLSCREEN);
    }
    al_set_app_name(applicationConfig.strAppName.c_str());
    al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_REQUIRE);
    display = al_create_display(applicationConfig.iDispW, applicationConfig.iDispH);

    al_install_keyboard();
    al_install_mouse();
    al_init_primitives_addon();
    al_init_image_addon();
    al_init_font_addon();
    al_init_ttf_addon();

    timer = al_create_timer(applicationConfig.dFps);
    queue = al_create_event_queue();
    textFont = al_load_ttf_font(styleConfig.strFontPath.c_str(), styleConfig.iFontSize, NULL);

    if ((display == nullptr) || (timer == nullptr) || (queue == nullptr) || (textFont == nullptr))
    {
        std::cout << "ERROR: Either the display, timer, queue or font failed to initialize!" << std::endl
            << "0x" << display << " 0x" << timer << " 0x" << queue << " 0x" << textFont << std::endl;
        return false;
    }

    al_register_event_source(queue, al_get_keyboard_event_source());
    al_register_event_source(queue, al_get_mouse_event_source());
    al_register_event_source(queue, al_get_display_event_source(display));
    al_register_event_source(queue, al_get_timer_event_source(timer));

    return true;
}

void AppBody()
{
    //tmx_img_load_func = al_img_loader2;
    //tmx_img_free_func = (void(*)(void*))al_destroy_bitmap;

    bool done = false;
    bool redraw = false;

    TileMap map("data/maps/test.tmx");
    std::cout << "walk on 0,0? " << map.CanWalktoTileAt(0, 0) << std::endl;
    std::cout << "walk on 1,1? " << map.CanWalktoTileAt(1, 1) << std::endl;
    std::cout << "walk on 39,29? " << map.CanWalktoTileAt(39, 29) << std::endl;
    std::cout << "walk on 40,30? " << map.CanWalktoTileAt(40, 30) << std::endl;

    int x_offset = 0, y_offset = 0;
    int x_delta, y_delta;
    int key_state[2] = { 0, 0 };

    x_delta = applicationConfig.iDispW - al_get_bitmap_width(map.GetFullMap());
    y_delta = applicationConfig.iDispH - al_get_bitmap_height(map.GetFullMap());

    al_start_timer(timer);
    while (!done)
    {
        ALLEGRO_EVENT ev;
        al_wait_for_event(queue, &ev);

        switch (ev.type)
        {
            case ALLEGRO_EVENT_TIMER:
                x_offset += key_state[0];
                y_offset += key_state[1];
                if (x_delta > 0)
                {
                    x_offset = x_delta / 2;
                } else
                {
                    if (x_offset < x_delta) x_offset = x_delta;
                    if (x_offset > 0) x_offset = 0;
                }
                if (y_delta > 0)
                {
                    y_offset = y_delta / 2;
                } else
                {
                    if (y_offset < y_delta) y_offset = y_delta;
                    if (y_offset > 0) y_offset = 0;
                }

                redraw = true;
                break;
            case ALLEGRO_EVENT_DISPLAY_CLOSE:
                done = true;
                break;
            case ALLEGRO_EVENT_KEY_DOWN:
                if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
                {
                    done = true;
                }

                switch (ev.keyboard.keycode)
                {
                    case ALLEGRO_KEY_LEFT:  key_state[0] = 4; break;
                    case ALLEGRO_KEY_RIGHT: key_state[0] = -4; break;
                    case ALLEGRO_KEY_UP:    key_state[1] = 4; break;
                    case ALLEGRO_KEY_DOWN:  key_state[1] = -4; break;
                }

                break;
            case ALLEGRO_EVENT_KEY_UP:
                switch (ev.keyboard.keycode)
                {
                    case ALLEGRO_KEY_LEFT:
                    case ALLEGRO_KEY_RIGHT: key_state[0] = 0; break;
                    case ALLEGRO_KEY_UP:
                    case ALLEGRO_KEY_DOWN:  key_state[1] = 0; break;
                }
                break;
            default:
                break;
        }

        if (redraw && al_is_event_queue_empty(queue))
        {
            redraw = false;
            al_clear_to_color(styleConfig.colBackgroundColor);
            al_draw_bitmap(map.GetFullMap(), x_offset, y_offset, NULL);
            al_flip_display();
        }
    }
}

void Shutdown()
{
    al_destroy_display(display);
    al_destroy_event_queue(queue);
    al_destroy_timer(timer);
    al_destroy_font(textFont);

    std::cout << "Termination successfull, now quiting..." << std::endl;
}

int main(int argc, char** argv)
{
    if (Init() == false)
    {
        std::cout << "Fatal error! Closing application..." << std::endl;
        al_rest(10.0);
        return EXIT_FAILURE;
    }

    AppBody();
    Shutdown();

    al_rest(0.5);
    return EXIT_SUCCESS;
}

<commit_msg>Draw individual layers on diferent draw calls<commit_after>// MainGame.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "src\Tool\Init.h"
#include "src\tilemap.h"

ALLEGRO_DISPLAY     *display = nullptr;
ALLEGRO_EVENT_QUEUE *queue = nullptr;
ALLEGRO_TIMER       *timer = nullptr;
ALLEGRO_FONT        *textFont = nullptr;

InitData  applicationConfig;
StyleData styleConfig;

bool Init()
{
    if (LoadConfigurationData(applicationConfig, styleConfig) == false)
        return false;

    al_init();

    if (applicationConfig.bfullscreen == true)
    {
        al_set_new_display_flags(ALLEGRO_FULLSCREEN);
    }
    al_set_app_name(applicationConfig.strAppName.c_str());
    al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_REQUIRE);
    display = al_create_display(applicationConfig.iDispW, applicationConfig.iDispH);

    al_install_keyboard();
    al_install_mouse();
    al_init_primitives_addon();
    al_init_image_addon();
    al_init_font_addon();
    al_init_ttf_addon();

    timer = al_create_timer(applicationConfig.dFps);
    queue = al_create_event_queue();
    textFont = al_load_ttf_font(styleConfig.strFontPath.c_str(), styleConfig.iFontSize, NULL);

    if ((display == nullptr) || (timer == nullptr) || (queue == nullptr) || (textFont == nullptr))
    {
        std::cout << "ERROR: Either the display, timer, queue or font failed to initialize!" << std::endl
            << "0x" << display << " 0x" << timer << " 0x" << queue << " 0x" << textFont << std::endl;
        return false;
    }

    al_register_event_source(queue, al_get_keyboard_event_source());
    al_register_event_source(queue, al_get_mouse_event_source());
    al_register_event_source(queue, al_get_display_event_source(display));
    al_register_event_source(queue, al_get_timer_event_source(timer));

    return true;
}

void AppBody()
{
    //tmx_img_load_func = al_img_loader2;
    //tmx_img_free_func = (void(*)(void*))al_destroy_bitmap;

    bool done = false;
    bool redraw = false;

    TileMap map("data/maps/test.tmx");

    int x_offset = 0, y_offset = 0;
    int x_delta, y_delta;
    int key_state[2] = { 0, 0 };

    x_delta = applicationConfig.iDispW - al_get_bitmap_width(map.GetFullMap());
    y_delta = applicationConfig.iDispH - al_get_bitmap_height(map.GetFullMap());

    al_start_timer(timer);
    while (!done)
    {
        ALLEGRO_EVENT ev;
        al_wait_for_event(queue, &ev);

        switch (ev.type)
        {
            case ALLEGRO_EVENT_TIMER:
                x_offset += key_state[0];
                y_offset += key_state[1];
                if (x_delta > 0)
                {
                    x_offset = x_delta / 2;
                } else
                {
                    if (x_offset < x_delta) x_offset = x_delta;
                    if (x_offset > 0) x_offset = 0;
                }
                if (y_delta > 0)
                {
                    y_offset = y_delta / 2;
                } else
                {
                    if (y_offset < y_delta) y_offset = y_delta;
                    if (y_offset > 0) y_offset = 0;
                }

                redraw = true;
                break;
            case ALLEGRO_EVENT_DISPLAY_CLOSE:
                done = true;
                break;
            case ALLEGRO_EVENT_KEY_DOWN:
                if (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
                {
                    done = true;
                }

                switch (ev.keyboard.keycode)
                {
                    case ALLEGRO_KEY_LEFT:  key_state[0] = 4; break;
                    case ALLEGRO_KEY_RIGHT: key_state[0] = -4; break;
                    case ALLEGRO_KEY_UP:    key_state[1] = 4; break;
                    case ALLEGRO_KEY_DOWN:  key_state[1] = -4; break;
                }

                break;
            case ALLEGRO_EVENT_KEY_UP:
                switch (ev.keyboard.keycode)
                {
                    case ALLEGRO_KEY_LEFT:
                    case ALLEGRO_KEY_RIGHT: key_state[0] = 0; break;
                    case ALLEGRO_KEY_UP:
                    case ALLEGRO_KEY_DOWN:  key_state[1] = 0; break;
                }
                break;
            default:
                break;
        }

        if (redraw && al_is_event_queue_empty(queue))
        {
            redraw = false;
            al_clear_to_color(styleConfig.colBackgroundColor);

            al_draw_bitmap(map.GetLayerMap("Terrain"), x_offset, y_offset, 0);
            /*
            Playable characters should draw on this position
            */
            al_draw_bitmap(map.GetLayerMap("Buildings"), x_offset, y_offset, 0);
            al_draw_bitmap(map.GetLayerMap("Decoration"), x_offset, y_offset, 0);

            al_flip_display();
        }
    }
}

void Shutdown()
{
    al_destroy_display(display);
    al_destroy_event_queue(queue);
    al_destroy_timer(timer);
    al_destroy_font(textFont);

    std::cout << "Termination successfull, now quiting..." << std::endl;
}

int main(int argc, char** argv)
{
    if (Init() == false)
    {
        std::cout << "Fatal error! Closing application..." << std::endl;
        al_rest(10.0);
        return EXIT_FAILURE;
    }

    AppBody();
    Shutdown();

    al_rest(0.5);
    return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/

/* Originally by Brad Garton and Doug Scott (SGI code) and Dave Topper
   (Linux code). Reworked for v2.3 by John Gibson.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <errno.h>
#include <assert.h>
#include <globals.h>
#include <audio_port.h>
#include <sndlibsupport.h>
#include "../rtstuff/rtdefs.h"

/* #define DEBUG */

/* ---------------------------------------------------------- rtsetparams --- */
/* Minc function that sets output sampling rate (p0), maximum number of
   output channels (p1), and (optionally) I/O buffer size (p2).

   On SGI, the optional p3 lets you specify the output port as a string
   (e.g., "LINE", "DIGITAL", etc.).

   Based on this information, rtsetparams allocates a mono output buffer
   for each of the output channels, and opens output devices.
*/
double
rtsetparams(float p[], int n_args, double pp[])
{
   int         i, status;
   int         verbose = print_is_on;
#ifdef SGI
   static char *out_port_str = NULL;
#endif /* SGI */

   if (rtsetparams_called) {
      fprintf(stderr, "You can only use rtsetparams once!\n");
      exit(1);
   }
   rtsetparams_called = 1;

// FIXME: Need better names for NCHANS and RTBUFSAMPS. -JGG

   SR = p[0];
   NCHANS = (int) p[1];
   RTBUFSAMPS = n_args > 2 ? (int) p[2] : 8192;

   if (n_args > 3) {
#ifdef SGI
      /* Cast Minc double to char ptr to get string. */
      int iarg = (int) pp[3];
      out_port_str = (char *) iarg;
      if (verbose)
         printf("Playing through output port '%s'\n", out_port_str);
#endif /* SGI */
   }

   if (NCHANS > MAXBUS) {
      fprintf(stderr, "You can only have %d output channels.\n", MAXBUS);
      exit(1);
   }

   /* play_audio is true unless user has called set_option("audio_off") before
      rtsetparams. This would let user run multiple jobs, as long as only one
      needs the audio drivers.  -JGG
   */
   if (play_audio) {
      int in_nchans, nframes = RTBUFSAMPS;

      /* Open audio input and output ports. */
#ifdef LINUX
      if (full_duplex)
         in_nchans = NCHANS;
      else
         in_nchans = 0;

      status = open_ports(in_nchans, MAXBUS, in_port, NCHANS, MAXBUS, out_port,
                                         verbose, SR, NUM_FRAGMENTS, &nframes);
#endif /* LINUX */
#ifdef SGI
      status = open_sgi_ports(out_port_str, NCHANS, &out_port, verbose, SR,
                                                                     &nframes);
#endif /* SGI */
      if (status == -1) {
         fprintf(stderr, "Trouble opening audio ports.\n");
         exit(1);
      }

      /* This may have been reset by driver. */
      RTBUFSAMPS = nframes;
   }

   /* inTraverse waits for this. Set it even if play_audio is false! */
   audio_config = 1;

   if (verbose)
      printf("Audio set:  %g sampling rate, %d channels\n", SR, NCHANS);

   /* Allocate output buffers. Do this *after* opening audio devices,
      in case OSS changes our buffer size, for example.
   */
   for (i = 0; i < NCHANS; i++) {
      allocate_out_buffer(i, RTBUFSAMPS);
   }

   return 0.0;
}

/* ---------------------------------------------------- close_audio_ports --- */
/* NOTE: This is here, rather than in audio_port.c, because it needs globals
   that we'd prefer to hide from utility programs (like cmixplay.c) that
   use audio_port.c.    -JGG
*/
void
close_audio_ports()
{
   int n;

#ifdef LINUX
 #ifdef MONO_DEVICES
   for (n = 0; n < NCHANS; n++)
      if (out_port[n])
         close(out_port[n]);
   for (n = 0; n < audioNCHANS; n++)
      if (in_port[n])
         close(in_port[n]);
 #else /* !MONO_DEVICES */
   if (out_port[0])
      close(out_port[0]);
   if (in_port[0] && in_port[0] != out_port[0])
      close(in_port[0]);
 #endif /* !MONO_DEVICES */
#endif /* LINUX */

#ifdef SGI
   if (out_port) {
      while (ALgetfilled(out_port) > 0)
         ;
// FIXME: anything else?
   }
#endif /* SGI */
}

<commit_msg>Changed default buffer size to 4096<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/

/* Originally by Brad Garton and Doug Scott (SGI code) and Dave Topper
   (Linux code). Reworked for v2.3 by John Gibson.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <errno.h>
#include <assert.h>
#include <globals.h>
#include <audio_port.h>
#include <sndlibsupport.h>
#include "../rtstuff/rtdefs.h"

/* #define DEBUG */

/* ---------------------------------------------------------- rtsetparams --- */
/* Minc function that sets output sampling rate (p0), maximum number of
   output channels (p1), and (optionally) I/O buffer size (p2).

   On SGI, the optional p3 lets you specify the output port as a string
   (e.g., "LINE", "DIGITAL", etc.).

   Based on this information, rtsetparams allocates a mono output buffer
   for each of the output channels, and opens output devices.
*/
double
rtsetparams(float p[], int n_args, double pp[])
{
   int         i, status;
   int         verbose = print_is_on;
#ifdef SGI
   static char *out_port_str = NULL;
#endif /* SGI */

   if (rtsetparams_called) {
      fprintf(stderr, "You can only use rtsetparams once!\n");
      exit(1);
   }
   rtsetparams_called = 1;

// FIXME: Need better names for NCHANS and RTBUFSAMPS. -JGG

   SR = p[0];
   NCHANS = (int) p[1];
   RTBUFSAMPS = n_args > 2 ? (int) p[2] : 4096;

   if (n_args > 3) {
#ifdef SGI
      /* Cast Minc double to char ptr to get string. */
      int iarg = (int) pp[3];
      out_port_str = (char *) iarg;
      if (verbose)
         printf("Playing through output port '%s'\n", out_port_str);
#endif /* SGI */
   }

   if (NCHANS > MAXBUS) {
      fprintf(stderr, "You can only have %d output channels.\n", MAXBUS);
      exit(1);
   }

   /* play_audio is true unless user has called set_option("audio_off") before
      rtsetparams. This would let user run multiple jobs, as long as only one
      needs the audio drivers.  -JGG
   */
   if (play_audio) {
      int in_nchans, nframes = RTBUFSAMPS;

      /* Open audio input and output ports. */
#ifdef LINUX
      if (full_duplex)
         in_nchans = NCHANS;
      else
         in_nchans = 0;

      status = open_ports(in_nchans, MAXBUS, in_port, NCHANS, MAXBUS, out_port,
                                         verbose, SR, NUM_FRAGMENTS, &nframes);
#endif /* LINUX */
#ifdef SGI
      status = open_sgi_ports(out_port_str, NCHANS, &out_port, verbose, SR,
                                                                     &nframes);
#endif /* SGI */
      if (status == -1) {
         fprintf(stderr, "Trouble opening audio ports.\n");
         exit(1);
      }

      /* This may have been reset by driver. */
      RTBUFSAMPS = nframes;
   }

   /* inTraverse waits for this. Set it even if play_audio is false! */
   audio_config = 1;

   if (verbose)
      printf("Audio set:  %g sampling rate, %d channels\n", SR, NCHANS);

   /* Allocate output buffers. Do this *after* opening audio devices,
      in case OSS changes our buffer size, for example.
   */
   for (i = 0; i < NCHANS; i++) {
      allocate_out_buffer(i, RTBUFSAMPS);
   }

   return 0.0;
}

/* ---------------------------------------------------- close_audio_ports --- */
/* NOTE: This is here, rather than in audio_port.c, because it needs globals
   that we'd prefer to hide from utility programs (like cmixplay.c) that
   use audio_port.c.    -JGG
*/
void
close_audio_ports()
{
   int n;

#ifdef LINUX
 #ifdef MONO_DEVICES
   for (n = 0; n < NCHANS; n++)
      if (out_port[n])
         close(out_port[n]);
   for (n = 0; n < audioNCHANS; n++)
      if (in_port[n])
         close(in_port[n]);
 #else /* !MONO_DEVICES */
   if (out_port[0])
      close(out_port[0]);
   if (in_port[0] && in_port[0] != out_port[0])
      close(in_port[0]);
 #endif /* !MONO_DEVICES */
#endif /* LINUX */

#ifdef SGI
   if (out_port) {
      while (ALgetfilled(out_port) > 0)
         ;
// FIXME: anything else?
   }
#endif /* SGI */
}

<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/

/* Originally by Brad Garton and Doug Scott (SGI code) and Dave Topper
   (Linux code). Reworked for v2.3 by John Gibson.
   Reworked to use new AudioDevice code for v3.7 by Douglas Scott.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <errno.h>
#include <assert.h>
#include <globals.h>
#include "audio_devices.h"
#include <ugens.h>
#include "../rtstuff/rtdefs.h"

/* #define DEBUG */

/* ---------------------------------------------------------- rtsetparams --- */
/* Minc function that sets output sampling rate (p0), maximum number of
   output channels (p1), and (optionally) I/O buffer size (p2).

   On SGI, the optional p3 lets you specify the output port as a string
   (e.g., "LINE", "DIGITAL", etc.).

   Based on this information, rtsetparams allocates a mono output buffer
   for each of the output channels, and opens output devices.
*/
double
rtsetparams(float p[], int n_args, double pp[])
{
   int         i, status;
   int         verbose = print_is_on;
#ifdef SGI
   static char *out_port_str = NULL;
#endif /* SGI */

   if (rtsetparams_called) {
      die("rtsetparams", "You can only call rtsetparams once!");
   }

// FIXME: Need better names for NCHANS and RTBUFSAMPS. -JGG

   SR = p[0];
   NCHANS = (int) p[1];
   RTBUFSAMPS = n_args > 2 ? (int) p[2] : 4096;

   if (n_args > 3 && pp[3] != 0.0) {
#ifdef SGI
      /* Cast Minc double to char ptr to get string. */
      int iarg = (int) pp[3];
      out_port_str = (char *) iarg;
 	  advise("rtsetparams", "Playing through output port '%s'", out_port_str);
#endif /* SGI */
   }

   if (SR <= 0.0) {
	   die("rtsetparams", "Sampling rate must be greater than 0.");
   }

   if (NCHANS > MAXBUS) {
      die("rtsetparams", "You can only have up to %d output channels.", MAXBUS);
   }

   /* play_audio is true unless user has called set_option("audio_off") before
      rtsetparams. This would let user run multiple jobs, as long as only one
      needs the audio drivers.  -JGG
   */
   if (play_audio) {
      int nframes = RTBUFSAMPS;

	  if (create_audio_devices(full_duplex, NCHANS, SR, &nframes) < 0)
	  	return -1;

      /* This may have been reset by driver. */
      RTBUFSAMPS = nframes;
   }

   /* inTraverse waits for this. Set it even if play_audio is false! */
   pthread_mutex_lock(&audio_config_lock);
   audio_config = 1;
   pthread_mutex_unlock(&audio_config_lock);

   if (verbose)
      printf("Audio set:  %g sampling rate, %d channels\n", SR, NCHANS);

   /* Allocate output buffers. Do this *after* opening audio devices,
      in case OSS changes our buffer size, for example.
   */
   for (i = 0; i < NCHANS; i++) {
      allocate_out_buffer(i, RTBUFSAMPS);
   }

   rtsetparams_called = 1;	/* Put this at end to allow re-call due to error */

   return 0;
}

/* ---------------------------------------------------- close_audio_ports --- */
/* NOTE: This is here, rather than in audio_port.c, because it needs globals
   that we'd prefer to hide from utility programs (like cmixplay.c) that
   use audio_port.c.    -JGG
*/
void
close_audio_ports()
{
   int n;

	// This closes and destroys the AudioDevices for input and output.
	destroy_audio_devices();

#ifdef LINUX
 #ifdef MONO_DEVICES
   for (n = 0; n < NCHANS; n++)
      if (out_port[n])
         close(out_port[n]);
   for (n = 0; n < audioNCHANS; n++)
      if (in_port[n])
         close(in_port[n]);
 #else /* !MONO_DEVICES */

   if (in_port[0] && in_port[0] != out_port[0])
      close(in_port[0]);
 #endif /* !MONO_DEVICES */
#endif /* LINUX */
}

<commit_msg>Added "return -1" to blocks which used die();  Cleaned up.  Changed audio code to use independent record_audio and play_audio variables.<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/

/* Originally by Brad Garton and Doug Scott (SGI code) and Dave Topper
   (Linux code). Reworked for v2.3 by John Gibson.
   Reworked to use new AudioDevice code for v3.7 by Douglas Scott.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <errno.h>
#include <assert.h>
#include <globals.h>
#include "audio_devices.h"
#include <ugens.h>
#include "../rtstuff/rtdefs.h"

/* #define DEBUG */

/* ---------------------------------------------------------- rtsetparams --- */
/* Minc function that sets output sampling rate (p0), maximum number of
   output channels (p1), and (optionally) I/O buffer size (p2).

   On SGI, the optional p3 lets you specify the output port as a string
   (e.g., "LINE", "DIGITAL", etc.).

   Based on this information, rtsetparams allocates a mono output buffer
   for each of the output channels, and opens output devices.
*/
double
rtsetparams(float p[], int n_args, double pp[])
{
   int         i, status;
   int         verbose = print_is_on;
#ifdef SGI
   static char *out_port_str = NULL;
#endif /* SGI */

   if (rtsetparams_called) {
      die("rtsetparams", "You can only call rtsetparams once!");
	  return -1;
   }

// FIXME: Need better names for NCHANS and RTBUFSAMPS. -JGG

   SR = p[0];
   NCHANS = (int) p[1];
   RTBUFSAMPS = n_args > 2 ? (int) p[2] : 4096;

   if (n_args > 3 && pp[3] != 0.0) {
#ifdef SGI
      /* Cast Minc double to char ptr to get string. */
      int iarg = (int) pp[3];
      out_port_str = (char *) iarg;
 	  advise("rtsetparams", "Playing through output port '%s'", out_port_str);
#endif /* SGI */
   }

   if (SR <= 0.0) {
	   die("rtsetparams", "Sampling rate must be greater than 0.");
	   return -1;
   }

   if (NCHANS > MAXBUS) {
      die("rtsetparams", "You can only have up to %d output channels.", MAXBUS - 1);
	  return -1;
   }

   /* play_audio is true unless user has called set_option("audio_off") before
      rtsetparams. This would let user run multiple jobs, as long as only one
      needs the audio drivers.  -JGG

	  record_audio is false unless user has called set_option("full_duplex_on") or
	  has explicity turned record on by itself via set_option("record_on"), or
	  has already called rtinput("AUDIO").  -DS
   */
   if (play_audio || record_audio) {
      int nframes = RTBUFSAMPS;

	  if (create_audio_devices(record_audio, play_audio, NCHANS, SR, &nframes) < 0)
	  	return -1;

      /* This may have been reset by driver. */
      RTBUFSAMPS = nframes;
   }

   /* inTraverse waits for this. Set it even if play_audio is false! */
   pthread_mutex_lock(&audio_config_lock);
   audio_config = 1;
   pthread_mutex_unlock(&audio_config_lock);

   if (verbose)
      printf("Audio set:  %g sampling rate, %d channels\n", SR, NCHANS);

   /* Allocate output buffers. Do this *after* opening audio devices,
      in case OSS changes our buffer size, for example.
   */
   for (i = 0; i < NCHANS; i++) {
      allocate_out_buffer(i, RTBUFSAMPS);
   }

   rtsetparams_called = 1;	/* Put this at end to allow re-call due to error */

   return 0;
}

/* ---------------------------------------------------- close_audio_ports --- */
/* NOTE: This is here, rather than in audio_port.c, because it needs globals
   that we'd prefer to hide from utility programs (like cmixplay.c) that
   use audio_port.c.    -JGG
*/
void
close_audio_ports()
{
	// This closes and destroys the AudioDevices for input and output.
	destroy_audio_devices();
}

<|endoftext|>


<commit_before>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2014 Mohammed Sameer <msameer@foolab.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "fsmonitor.h"
#include <qmusbmode.h>
#include <sys/statvfs.h>
#include <cstdio>

#define MIN_SPACE 100 * 1024 * 1024 // 100 MB

FSMonitor::FSMonitor(QObject *parent) :
  QObject(parent) {

}

FSMonitor::~FSMonitor() {

}

bool FSMonitor::isAvailable() const {
  return true;
}

bool FSMonitor::hasFreeSpace(const QString& path) {
  struct statvfs buf;

  if (statvfs(path.toLocal8Bit().data(), &buf) == -1) {
    std::perror("statvfs");
    return false;
  }

  // If the user has a lot of free space (8 GB for example)
  // then we will overflow the unsigned long int thus we use a 64 bits "int"
  quint64 freeSpace = (quint64)buf.f_bsize * (quint64)buf.f_bavail;
  return (freeSpace >= MIN_SPACE);
}
<commit_msg>sailfish: remove unneeded qmusbmode.h include from fsmonitor.cpp<commit_after>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2014 Mohammed Sameer <msameer@foolab.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "fsmonitor.h"
#include <sys/statvfs.h>
#include <cstdio>

#define MIN_SPACE 100 * 1024 * 1024 // 100 MB

FSMonitor::FSMonitor(QObject *parent) :
  QObject(parent) {

}

FSMonitor::~FSMonitor() {

}

bool FSMonitor::isAvailable() const {
  return true;
}

bool FSMonitor::hasFreeSpace(const QString& path) {
  struct statvfs buf;

  if (statvfs(path.toLocal8Bit().data(), &buf) == -1) {
    std::perror("statvfs");
    return false;
  }

  // If the user has a lot of free space (8 GB for example)
  // then we will overflow the unsigned long int thus we use a 64 bits "int"
  quint64 freeSpace = (quint64)buf.f_bsize * (quint64)buf.f_bavail;
  return (freeSpace >= MIN_SPACE);
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
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.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "Http/Request.h"
#include "RequestParser.h"

namespace http
{

RequestParser::RequestParser() : state_(method_start) {}

void RequestParser::Reset() { state_ = method_start; }

boost::tuple<boost::tribool, char *>
RequestParser::Parse(Request &req, char *begin, char *end, http::CompressionType *compressionType)
{
    while (begin != end)
    {
        boost::tribool result = consume(req, *begin++, compressionType);
        if (result || !result)
        {
            return boost::make_tuple(result, begin);
        }
    }
    boost::tribool result = boost::indeterminate;
    return boost::make_tuple(result, begin);
}

boost::tribool
RequestParser::consume(Request &req, char input, http::CompressionType *compressionType)
{
    switch (state_)
    {
    case method_start:
        if (!isChar(input) || isCTL(input) || isTSpecial(input))
        {
            return false;
        }
        state_ = method;
        return boost::indeterminate;
    case method:
        if (input == ' ')
        {
            state_ = uri;
            return boost::indeterminate;
        }
        if (!isChar(input) || isCTL(input) || isTSpecial(input))
        {
            return false;
        }
        return boost::indeterminate;
    case uri_start:
        if (isCTL(input))
        {
            return false;
        }
        state_ = uri;
        req.uri.push_back(input);
        return boost::indeterminate;
    case uri:
        if (input == ' ')
        {
            state_ = http_version_h;
            return boost::indeterminate;
        }
        if (isCTL(input))
        {
            return false;
        }
        req.uri.push_back(input);
        return boost::indeterminate;
    case http_version_h:
        if (input == 'H')
        {
            state_ = http_version_t_1;
            return boost::indeterminate;
        }
        return false;
    case http_version_t_1:
        if (input == 'T')
        {
            state_ = http_version_t_2;
            return boost::indeterminate;
        }
        return false;
    case http_version_t_2:
        if (input == 'T')
        {
            state_ = http_version_p;
            return boost::indeterminate;
        }
        return false;
    case http_version_p:
        if (input == 'P')
        {
            state_ = http_version_slash;
            return boost::indeterminate;
        }
        return false;
    case http_version_slash:
        if (input == '/')
        {
            state_ = http_version_major_start;
            return boost::indeterminate;
        }
        return false;
    case http_version_major_start:
        if (isDigit(input))
        {
            state_ = http_version_major;
            return boost::indeterminate;
        }
        return false;
    case http_version_major:
        if (input == '.')
        {
            state_ = http_version_minor_start;
            return boost::indeterminate;
        }
        if (isDigit(input))
        {
            return boost::indeterminate;
        }
        return false;
    case http_version_minor_start:
        if (isDigit(input))
        {
            state_ = http_version_minor;
            return boost::indeterminate;
        }
        return false;
    case http_version_minor:
        if (input == '\r')
        {
            state_ = expecting_newline_1;
            return boost::indeterminate;
        }
        if (isDigit(input))
        {
            return boost::indeterminate;
        }
        return false;
    case expecting_newline_1:
        if (input == '\n')
        {
            state_ = header_line_start;
            return boost::indeterminate;
        }
        return false;
    case header_line_start:
        if (header.name == "Accept-Encoding")
        {
            /* giving gzip precedence over deflate */
            if (header.value.find("deflate") != std::string::npos)
            {
                *compressionType = deflateRFC1951;
            }
            if (header.value.find("gzip") != std::string::npos)
            {
                *compressionType = gzipRFC1952;
            }
        }

        if ("Referer" == header.name)
        {
            req.referrer = header.value;
        }

        if ("User-Agent" == header.name)
        {
            req.agent = header.value;
        }

        if (input == '\r')
        {
            state_ = expecting_newline_3;
            return boost::indeterminate;
        }
        if (!isChar(input) || isCTL(input) || isTSpecial(input))
        {
            return false;
        }
        state_ = header_name;
        header.Clear();
        header.name.push_back(input);
        return boost::indeterminate;
    case header_lws:
        if (input == '\r')
        {
            state_ = expecting_newline_2;
            return boost::indeterminate;
        }
        if (input == ' ' || input == '\t')
        {
            return boost::indeterminate;
        }
        if (isCTL(input))
        {
            return false;
        }
        state_ = header_value;
        return boost::indeterminate;
    case header_name:
        if (input == ':')
        {
            state_ = space_before_header_value;
            return boost::indeterminate;
        }
        if (!isChar(input) || isCTL(input) || isTSpecial(input))
        {
            return false;
        }
        header.name.push_back(input);
        return boost::indeterminate;
    case space_before_header_value:
        if (input == ' ')
        {
            state_ = header_value;
            return boost::indeterminate;
        }
        return false;
    case header_value:
        if (input == '\r')
        {
            state_ = expecting_newline_2;
            return boost::indeterminate;
        }
        if (isCTL(input))
        {
            return false;
        }
        header.value.push_back(input);
        return boost::indeterminate;
    case expecting_newline_2:
        if (input == '\n')
        {
            state_ = header_line_start;
            return boost::indeterminate;
        }
        return false;
    default: // expecting_newline_3:
        return (input == '\n');
    // default:
    //     return false;
    }
}

inline bool RequestParser::isChar(int c) { return c >= 0 && c <= 127; }

inline bool RequestParser::isCTL(int c) { return (c >= 0 && c <= 31) || (c == 127); }

inline bool RequestParser::isTSpecial(int c)
{
    switch (c)
    {
    case '(':
    case ')':
    case '<':
    case '>':
    case '@':
    case ',':
    case ';':
    case ':':
    case '\\':
    case '"':
    case '/':
    case '[':
    case ']':
    case '?':
    case '=':
    case '{':
    case '}':
    case ' ':
    case '\t':
        return true;
    default:
        return false;
    }
}

inline bool RequestParser::isDigit(int c) { return c >= '0' && c <= '9'; }
}
<commit_msg>rename variable<commit_after>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
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.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "Http/Request.h"
#include "RequestParser.h"

namespace http
{

RequestParser::RequestParser() : state_(method_start) {}

void RequestParser::Reset() { state_ = method_start; }

boost::tuple<boost::tribool, char *>
RequestParser::Parse(Request &req, char *begin, char *end, http::CompressionType *compression_type)
{
    while (begin != end)
    {
        boost::tribool result = consume(req, *begin++, compression_type);
        if (result || !result)
        {
            return boost::make_tuple(result, begin);
        }
    }
    boost::tribool result = boost::indeterminate;
    return boost::make_tuple(result, begin);
}

boost::tribool
RequestParser::consume(Request &req, char input, http::CompressionType *compression_type)
{
    switch (state_)
    {
    case method_start:
        if (!isChar(input) || isCTL(input) || isTSpecial(input))
        {
            return false;
        }
        state_ = method;
        return boost::indeterminate;
    case method:
        if (input == ' ')
        {
            state_ = uri;
            return boost::indeterminate;
        }
        if (!isChar(input) || isCTL(input) || isTSpecial(input))
        {
            return false;
        }
        return boost::indeterminate;
    case uri_start:
        if (isCTL(input))
        {
            return false;
        }
        state_ = uri;
        req.uri.push_back(input);
        return boost::indeterminate;
    case uri:
        if (input == ' ')
        {
            state_ = http_version_h;
            return boost::indeterminate;
        }
        if (isCTL(input))
        {
            return false;
        }
        req.uri.push_back(input);
        return boost::indeterminate;
    case http_version_h:
        if (input == 'H')
        {
            state_ = http_version_t_1;
            return boost::indeterminate;
        }
        return false;
    case http_version_t_1:
        if (input == 'T')
        {
            state_ = http_version_t_2;
            return boost::indeterminate;
        }
        return false;
    case http_version_t_2:
        if (input == 'T')
        {
            state_ = http_version_p;
            return boost::indeterminate;
        }
        return false;
    case http_version_p:
        if (input == 'P')
        {
            state_ = http_version_slash;
            return boost::indeterminate;
        }
        return false;
    case http_version_slash:
        if (input == '/')
        {
            state_ = http_version_major_start;
            return boost::indeterminate;
        }
        return false;
    case http_version_major_start:
        if (isDigit(input))
        {
            state_ = http_version_major;
            return boost::indeterminate;
        }
        return false;
    case http_version_major:
        if (input == '.')
        {
            state_ = http_version_minor_start;
            return boost::indeterminate;
        }
        if (isDigit(input))
        {
            return boost::indeterminate;
        }
        return false;
    case http_version_minor_start:
        if (isDigit(input))
        {
            state_ = http_version_minor;
            return boost::indeterminate;
        }
        return false;
    case http_version_minor:
        if (input == '\r')
        {
            state_ = expecting_newline_1;
            return boost::indeterminate;
        }
        if (isDigit(input))
        {
            return boost::indeterminate;
        }
        return false;
    case expecting_newline_1:
        if (input == '\n')
        {
            state_ = header_line_start;
            return boost::indeterminate;
        }
        return false;
    case header_line_start:
        if (header.name == "Accept-Encoding")
        {
            /* giving gzip precedence over deflate */
            if (header.value.find("deflate") != std::string::npos)
            {
                *compression_type = deflateRFC1951;
            }
            if (header.value.find("gzip") != std::string::npos)
            {
                *compression_type = gzipRFC1952;
            }
        }

        if ("Referer" == header.name)
        {
            req.referrer = header.value;
        }

        if ("User-Agent" == header.name)
        {
            req.agent = header.value;
        }

        if (input == '\r')
        {
            state_ = expecting_newline_3;
            return boost::indeterminate;
        }
        if (!isChar(input) || isCTL(input) || isTSpecial(input))
        {
            return false;
        }
        state_ = header_name;
        header.Clear();
        header.name.push_back(input);
        return boost::indeterminate;
    case header_lws:
        if (input == '\r')
        {
            state_ = expecting_newline_2;
            return boost::indeterminate;
        }
        if (input == ' ' || input == '\t')
        {
            return boost::indeterminate;
        }
        if (isCTL(input))
        {
            return false;
        }
        state_ = header_value;
        return boost::indeterminate;
    case header_name:
        if (input == ':')
        {
            state_ = space_before_header_value;
            return boost::indeterminate;
        }
        if (!isChar(input) || isCTL(input) || isTSpecial(input))
        {
            return false;
        }
        header.name.push_back(input);
        return boost::indeterminate;
    case space_before_header_value:
        if (input == ' ')
        {
            state_ = header_value;
            return boost::indeterminate;
        }
        return false;
    case header_value:
        if (input == '\r')
        {
            state_ = expecting_newline_2;
            return boost::indeterminate;
        }
        if (isCTL(input))
        {
            return false;
        }
        header.value.push_back(input);
        return boost::indeterminate;
    case expecting_newline_2:
        if (input == '\n')
        {
            state_ = header_line_start;
            return boost::indeterminate;
        }
        return false;
    default: // expecting_newline_3:
        return (input == '\n');
    // default:
    //     return false;
    }
}

inline bool RequestParser::isChar(int c) { return c >= 0 && c <= 127; }

inline bool RequestParser::isCTL(int c) { return (c >= 0 && c <= 31) || (c == 127); }

inline bool RequestParser::isTSpecial(int c)
{
    switch (c)
    {
    case '(':
    case ')':
    case '<':
    case '>':
    case '@':
    case ',':
    case ';':
    case ':':
    case '\\':
    case '"':
    case '/':
    case '[':
    case ']':
    case '?':
    case '=':
    case '{':
    case '}':
    case ' ':
    case '\t':
        return true;
    default:
        return false;
    }
}

inline bool RequestParser::isDigit(int c) { return c >= '0' && c <= '9'; }
}
<|endoftext|>


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

/*
Author: Chao Ma (mctt90@gmail.com)
This file is the implementation of FMScore class.
*/

#include <pmmintrin.h>  // for SSE

#include "src/score/fm_score_ftrl.h"
#include "src/base/math.h"

namespace xLearn {

// y = sum( (V_i*V_j)(x_i * x_j) )
// Using SSE to accelerate vector operation.
real_t FMScoreFtrl::CalcScore(const SparseRow* row,
                          Model& model,
                          real_t norm) {
  /*********************************************************
   *  linear term and bias term                            *
   *********************************************************/
  real_t sqrt_norm = sqrt(norm);
  real_t *w = model.GetParameter_w();
  real_t t = 0;
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    t += (iter->feat_val * w[iter->feat_id*3] * sqrt_norm);
  }
  // bias
  w = model.GetParameter_b();
  t += w[0];
  /*********************************************************
   *  latent factor                                        *
   *********************************************************/
  index_t aligned_k = model.get_aligned_k();
  index_t align0 = model.get_aligned_k() * 3;
  std::vector<real_t> sv(aligned_k, 0);
  real_t* s = sv.data();
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    index_t j1 = iter->feat_id;
    real_t v1 = iter->feat_val;
    real_t *w = model.GetParameter_v() + j1 * align0;
    __m128 XMMv = _mm_set1_ps(v1*norm);
    for (index_t d = 0; d < aligned_k; d += kAlign) {
      __m128 XMMs = _mm_load_ps(s+d);
      __m128 const XMMw = _mm_load_ps(w+d);
      XMMs = _mm_add_ps(XMMs, _mm_mul_ps(XMMw, XMMv));
      _mm_store_ps(s+d, XMMs);
    }
  }
  __m128 XMMt = _mm_set1_ps(0.0f);
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    index_t j1 = iter->feat_id;
    real_t v1 = iter->feat_val;
    real_t *w = model.GetParameter_v() + j1 * align0;
    __m128 XMMv = _mm_set1_ps(v1*norm);
    for (index_t d = 0; d < aligned_k; d += kAlign) {
      __m128 XMMs = _mm_load_ps(s+d);
      __m128 XMMw = _mm_load_ps(w+d);
      __m128 XMMwv = _mm_mul_ps(XMMw, XMMv);
      XMMt = _mm_add_ps(XMMt,
             _mm_mul_ps(XMMwv, _mm_sub_ps(XMMs, XMMwv)));
    }
  }
  XMMt = _mm_hadd_ps(XMMt, XMMt);
  XMMt = _mm_hadd_ps(XMMt, XMMt);
  real_t t_all;
  _mm_store_ss(&t_all, XMMt);
  t_all *= 0.5;
  t_all += t;
  return t_all;
}

// Calculate gradient and update current model parameters.
// Using SSE to accelerate vector operation.
void FMScoreFtrl::CalcGrad(const SparseRow* row,
                       Model& model,
                       real_t pg,
                       real_t norm) {
  /*********************************************************
   *  linear term and bias term                            *
   *********************************************************/
  real_t sqrt_norm = sqrt(norm);
  real_t *w = model.GetParameter_w();
  real_t alpha = .01;
  real_t beta = 1.0;
  real_t lambda1 = 2.0;
  real_t lambda2 = 4.0;
  for (SparseRow::const_iterator iter = row->begin();
      iter != row->end(); ++iter) {
    real_t gradient = pg * iter->feat_val;
    index_t idx_w = iter->feat_id * 3;
    index_t idx_n = idx_w + 1;
    index_t idx_z = idx_w + 2;
    real_t old_n =  w[idx_n];
    w[idx_n] += gradient * gradient;
    real_t sigma = 1.0f
                   * (std::sqrt(w[idx_n]) - std::sqrt(old_n))
                   / alpha;
    w[idx_z] += gradient - sigma * w[idx_w];

    if (std::abs(w[idx_z]) <= lambda1) {
      w[idx_w] = 0;
    } else {
      real_t smooth_lr = 1.0f
                         / (lambda2 + (beta + std::sqrt(w[idx_n])) / alpha);
      if (w[idx_z] < 0.0) {
        w[idx_z] += lambda1;
      } else if (w[idx_z] > 0.0) {
        w[idx_z] -= lambda1;
      }
      w[idx_w] = -1.0f * smooth_lr * w[idx_z];
    }
  }
  // bias
  w = model.GetParameter_b();
  real_t &wb = w[0];
  real_t &wbn = w[1];
  real_t &wbz = w[2];
  real_t g = pg; // g = pg * iter->feat_val; ?
  wbn += g*g;
  wbz += g;
  if (std::abs(wbz) <= lambda1) {
    wb = 0.0f;
  } else {
    real_t smooth_lr = 1.0f
                       / (lambda2 + (beta + std::sqrt(wbn)) / alpha);
    if (wbz < 0.0) {
      wbz += lambda1;
    } else if (wbz > 0.0) {
      wbz -= lambda1;
    }
    wb = -1.0f * smooth_lr * wbz;
  }
  /*********************************************************
   *  latent factor                                        *
   *********************************************************/
  index_t aligned_k = model.get_aligned_k();
  index_t align0 = model.get_aligned_k() * 3;
  __m128 XMMpg = _mm_set1_ps(pg);
  std::vector<real_t> sv(aligned_k, 0);
  real_t* s = sv.data();
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    index_t j1 = iter->feat_id;
    real_t v1 = iter->feat_val;
    real_t *w = model.GetParameter_v() + j1 * align0;
    __m128 XMMv = _mm_set1_ps(v1*norm);
    for (index_t d = 0; d < aligned_k; d += kAlign) {
      __m128 XMMs = _mm_load_ps(s+d);
      __m128 const XMMw = _mm_load_ps(w+d);
      XMMs = _mm_add_ps(XMMs, _mm_mul_ps(XMMw, XMMv));
      _mm_store_ps(s+d, XMMs);
    }
  }
  __m128 XMMcoef = _mm_set1_ps(-1.0);
  __m128 XMMalpha = _mm_set1_ps(alpha);
  __m128 XMMbeta = _mm_set1_ps(beta);
  __m128 XMMlambda1 = _mm_set1_ps(lambda1);
  __m128 XMMlambda2 = _mm_set1_ps(lambda2);
  __m128 XMMzero = _mm_set1_ps(0.0);
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    index_t j1 = iter->feat_id;
    real_t v1 = iter->feat_val;
    real_t *w = model.GetParameter_v() + j1 * align0;
    __m128 XMMv = _mm_set1_ps(v1*norm);
    __m128 XMMpgv = _mm_mul_ps(XMMpg, XMMv);
    for(index_t d = 0; d < aligned_k; d += kAlign) {
      __m128 XMMs = _mm_load_ps(s+d);
      __m128 XMMw = _mm_load_ps(w+d);
      __m128 XMMn = _mm_load_ps(w+aligned_k+d);
      __m128 XMMz = _mm_load_ps(w+aligned_k*2+d);
      __m128 XMMg = _mm_mul_ps(XMMpgv,
                    _mm_sub_ps(XMMs,
                    _mm_mul_ps(XMMw, XMMv)));
      __m128 XMMold_n = XMMn;
      XMMn = _mm_add_ps(XMMn,
             _mm_mul_ps(XMMg, XMMg));
      __m128 XMMsigma = _mm_mul_ps(
                        _mm_div_ps(
                        _mm_sub_ps(_mm_rsqrt_ps(XMMn),
                        _mm_rsqrt_ps(XMMold_n)), XMMalpha), XMMw);
      XMMz = _mm_sub_ps(
             _mm_add_ps(XMMz, XMMg), XMMsigma);
      static const union {
        int i[4];
        __m128 m;
      } __mm_abs_mask_cheat_ps = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
      __m128 XMMcomp_res = _mm_cmplt_ps(XMMlambda1,
                           _mm_and_ps(XMMz,
                          __mm_abs_mask_cheat_ps.m));
      real_t* comp_res;
      _mm_store_ps(comp_res, XMMcomp_res);
      if (comp_res) {
        __m128 XMMsmooth_lr = _mm_rcp_ps(
                              _mm_add_ps(XMMlambda2,
                              _mm_div_ps(
                              _mm_add_ps(XMMbeta,
                              _mm_rsqrt_ps(XMMn)),XMMalpha)));
        real_t* comp_z_lt_zero;
        _mm_store_ps(comp_z_lt_zero, _mm_cmplt_ps(XMMz, XMMzero));
        real_t* comp_z_gt_zero;
        _mm_store_ps(comp_z_gt_zero, _mm_cmpgt_ps(XMMz, XMMzero));
        if (comp_z_lt_zero) {
          XMMz = _mm_add_ps(XMMz, XMMlambda1);
        } else if(comp_z_gt_zero) {
          XMMz = _mm_sub_ps(XMMz, XMMlambda1);
        }
        XMMw = _mm_mul_ps(XMMcoef,
                          _mm_mul_ps(XMMsmooth_lr, XMMz));
      } else {
        XMMw = _mm_set1_ps(0.0);
      }
      _mm_store_ps(w+d, XMMw);
      _mm_store_ps(w+aligned_k+d, XMMn);
      _mm_store_ps(w+aligned_k*2+d, XMMz);
    }
  }
}

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

/*
Author: Chao Ma (mctt90@gmail.com)
This file is the implementation of FMScore class.
*/

#include <pmmintrin.h>  // for SSE

#include "src/score/fm_score_ftrl.h"
#include "src/base/math.h"

namespace xLearn {

// y = sum( (V_i*V_j)(x_i * x_j) )
// Using SSE to accelerate vector operation.
real_t FMScoreFtrl::CalcScore(const SparseRow* row,
                          Model& model,
                          real_t norm) {
  /*********************************************************
   *  linear term and bias term                            *
   *********************************************************/
  real_t sqrt_norm = sqrt(norm);
  real_t *w = model.GetParameter_w();
  real_t t = 0;
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    t += (iter->feat_val * w[iter->feat_id*3] * sqrt_norm);
  }
  // bias
  w = model.GetParameter_b();
  t += w[0];
  /*********************************************************
   *  latent factor                                        *
   *********************************************************/
  index_t aligned_k = model.get_aligned_k();
  index_t align0 = model.get_aligned_k() * 3;
  std::vector<real_t> sv(aligned_k, 0);
  real_t* s = sv.data();
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    index_t j1 = iter->feat_id;
    real_t v1 = iter->feat_val;
    real_t *w = model.GetParameter_v() + j1 * align0;
    __m128 XMMv = _mm_set1_ps(v1*norm);
    for (index_t d = 0; d < aligned_k; d += kAlign) {
      __m128 XMMs = _mm_load_ps(s+d);
      __m128 const XMMw = _mm_load_ps(w+d);
      XMMs = _mm_add_ps(XMMs, _mm_mul_ps(XMMw, XMMv));
      _mm_store_ps(s+d, XMMs);
    }
  }
  __m128 XMMt = _mm_set1_ps(0.0f);
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    index_t j1 = iter->feat_id;
    real_t v1 = iter->feat_val;
    real_t *w = model.GetParameter_v() + j1 * align0;
    __m128 XMMv = _mm_set1_ps(v1*norm);
    for (index_t d = 0; d < aligned_k; d += kAlign) {
      __m128 XMMs = _mm_load_ps(s+d);
      __m128 XMMw = _mm_load_ps(w+d);
      __m128 XMMwv = _mm_mul_ps(XMMw, XMMv);
      XMMt = _mm_add_ps(XMMt,
             _mm_mul_ps(XMMwv, _mm_sub_ps(XMMs, XMMwv)));
    }
  }
  XMMt = _mm_hadd_ps(XMMt, XMMt);
  XMMt = _mm_hadd_ps(XMMt, XMMt);
  real_t t_all;
  _mm_store_ss(&t_all, XMMt);
  t_all *= 0.5;
  t_all += t;
  return t_all;
}

// Calculate gradient and update current model parameters.
// Using SSE to accelerate vector operation.
void FMScoreFtrl::CalcGrad(const SparseRow* row,
                       Model& model,
                       real_t pg,
                       real_t norm) {
  /*********************************************************
   *  linear term and bias term                            *
   *********************************************************/
  real_t sqrt_norm = sqrt(norm);
  real_t *w = model.GetParameter_w();
  real_t alpha = .01;
  real_t beta = 1.0;
  real_t lambda1 = 2.0;
  real_t lambda2 = 4.0;
  for (SparseRow::const_iterator iter = row->begin();
      iter != row->end(); ++iter) {
    real_t gradient = pg * iter->feat_val;
    index_t idx_w = iter->feat_id * 3;
    index_t idx_n = idx_w + 1;
    index_t idx_z = idx_w + 2;
    real_t old_n =  w[idx_n];
    w[idx_n] += gradient * gradient;
    real_t sigma = 1.0f
                   * (std::sqrt(w[idx_n]) - std::sqrt(old_n))
                   / alpha;
    w[idx_z] += gradient - sigma * w[idx_w];

    if (std::abs(w[idx_z]) <= lambda1) {
      w[idx_w] = 0;
    } else {
      real_t smooth_lr = 1.0f
                         / (lambda2 + (beta + std::sqrt(w[idx_n])) / alpha);
      if (w[idx_z] < 0.0) {
        w[idx_z] += lambda1;
      } else if (w[idx_z] > 0.0) {
        w[idx_z] -= lambda1;
      }
      w[idx_w] = -1.0f * smooth_lr * w[idx_z];
    }
  }
  // bias
  w = model.GetParameter_b();
  real_t &wb = w[0];
  real_t &wbn = w[1];
  real_t &wbz = w[2];
  real_t g = pg; // g = pg * iter->feat_val; ?
  wbn += g*g;
  wbz += g;
  if (std::abs(wbz) <= lambda1) {
    wb = 0.0f;
  } else {
    real_t smooth_lr = 1.0f
                       / (lambda2 + (beta + std::sqrt(wbn)) / alpha);
    if (wbz < 0.0) {
      wbz += lambda1;
    } else if (wbz > 0.0) {
      wbz -= lambda1;
    }
    wb = -1.0f * smooth_lr * wbz;
  }
  /*********************************************************
   *  latent factor                                        *
   *********************************************************/
  index_t aligned_k = model.get_aligned_k();
  index_t align0 = model.get_aligned_k() * 3;
  __m128 XMMpg = _mm_set1_ps(pg);
  std::vector<real_t> sv(aligned_k, 0);
  real_t* s = sv.data();
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    index_t j1 = iter->feat_id;
    real_t v1 = iter->feat_val;
    real_t *w = model.GetParameter_v() + j1 * align0;
    __m128 XMMv = _mm_set1_ps(v1*norm);
    for (index_t d = 0; d < aligned_k; d += kAlign) {
      __m128 XMMs = _mm_load_ps(s+d);
      __m128 const XMMw = _mm_load_ps(w+d);
      XMMs = _mm_add_ps(XMMs, _mm_mul_ps(XMMw, XMMv));
      _mm_store_ps(s+d, XMMs);
    }
  }
  __m128 XMMcoef = _mm_set1_ps(-1.0);
  __m128 XMMalpha = _mm_set1_ps(alpha);
  __m128 XMMbeta = _mm_set1_ps(beta);
  __m128 XMMlambda1 = _mm_set1_ps(lambda1);
  __m128 XMMlambda2 = _mm_set1_ps(lambda2);
  __m128 XMMzero = _mm_set1_ps(0.0);
  for (SparseRow::const_iterator iter = row->begin();
       iter != row->end(); ++iter) {
    index_t j1 = iter->feat_id;
    real_t v1 = iter->feat_val;
    real_t *w = model.GetParameter_v() + j1 * align0;
    __m128 XMMv = _mm_set1_ps(v1*norm);
    __m128 XMMpgv = _mm_mul_ps(XMMpg, XMMv);
    for(index_t d = 0; d < aligned_k; d += kAlign) {
      __m128 XMMs = _mm_load_ps(s+d);
      __m128 XMMw = _mm_load_ps(w+d);
      __m128 XMMn = _mm_load_ps(w+aligned_k+d);
      __m128 XMMz = _mm_load_ps(w+aligned_k*2+d);
      __m128 XMMg = _mm_mul_ps(XMMpgv,
                    _mm_sub_ps(XMMs,
                    _mm_mul_ps(XMMw, XMMv)));
      __m128 XMMold_n = XMMn;
      XMMn = _mm_add_ps(XMMn,
             _mm_mul_ps(XMMg, XMMg));
      __m128 XMMsigma = _mm_mul_ps(
                        _mm_div_ps(
                        _mm_sub_ps(_mm_rsqrt_ps(XMMn),
                        _mm_rsqrt_ps(XMMold_n)), XMMalpha), XMMw);
      XMMz = _mm_sub_ps(
             _mm_add_ps(XMMz, XMMg), XMMsigma);
      static const union {
        int i[4];
        __m128 m;
      } __mm_abs_mask_cheat_ps = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
      __m128 XMMcomp_res = _mm_cmplt_ps(XMMlambda1,
                           _mm_and_ps(XMMz,
                          __mm_abs_mask_cheat_ps.m));
      real_t* comp_res;
      _mm_store_ps(comp_res, XMMcomp_res);
      if (comp_res) {
        __m128 XMMsmooth_lr = _mm_rcp_ps(
                              _mm_add_ps(XMMlambda2,
                              _mm_div_ps(
                              _mm_add_ps(XMMbeta,
                              _mm_rsqrt_ps(XMMn)),XMMalpha)));
        real_t* comp_z_lt_zero;
        _mm_store_ps(comp_z_lt_zero, _mm_cmplt_ps(XMMz, XMMzero));
        real_t* comp_z_gt_zero;
        _mm_store_ps(comp_z_gt_zero, _mm_cmpgt_ps(XMMzero, XMMz));
        if (comp_z_lt_zero) {
          XMMz = _mm_add_ps(XMMz, XMMlambda1);
        } else if(comp_z_gt_zero) {
          XMMz = _mm_sub_ps(XMMz, XMMlambda1);
        }
        XMMw = _mm_mul_ps(XMMcoef,
                          _mm_mul_ps(XMMsmooth_lr, XMMz));
      } else {
        XMMw = _mm_set1_ps(0.0);
      }
      _mm_store_ps(w+d, XMMw);
      _mm_store_ps(w+aligned_k+d, XMMn);
      _mm_store_ps(w+aligned_k*2+d, XMMz);
    }
  }
}

} // namespace xLearn
<|endoftext|>


<commit_before>/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#include "../c/util/crypto.h"
#include "../c/encoding/binary-xml-data.h"
#include "../encoding/binary-xml-encoder.hpp"
#include <ndn-cpp/sha256-with-rsa-signature.hpp>
#include "../util/logging.hpp"
#include <ndn-cpp/security/security-exception.hpp>
#include <ndn-cpp/security/policy/policy-manager.hpp>
#include "policy/validation-request.hpp"
#include <ndn-cpp/security/key-chain.hpp>

using namespace std;
using namespace ndn::ptr_lib;

namespace ndn {

KeyChain::KeyChain(const shared_ptr<IdentityManager>& identityManager, const shared_ptr<PolicyManager>& policyManager)
: identityManager_(identityManager), policyManager_(policyManager), face_(0), maxSteps_(100)
{
}

void
KeyChain::sign(Data& data, const Name& certificateName, WireFormat& wireFormat)
{
  identityManager_->signByCertificate(data, certificateName, wireFormat);
}

shared_ptr<Signature>
KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
{
  return identityManager_->signByCertificate(buffer, bufferLength, certificateName);
}

void
KeyChain::signByIdentity(Data& data, const Name& identityName, WireFormat& wireFormat)
{
  Name signingCertificateName;

  if (identityName.getComponentCount() == 0) {
    Name inferredIdentity = policyManager_->inferSigningIdentity(data.getName());
    if (inferredIdentity.getComponentCount() == 0)
      signingCertificateName = identityManager_->getDefaultCertificateName();
    else
      signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(inferredIdentity);
  }
  else
    signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(identityName);

  if (signingCertificateName.getComponentCount() == 0)
    throw SecurityException("No qualified certificate name found!");

  if (!policyManager_->checkSigningPolicy(data.getName(), signingCertificateName))
    throw SecurityException("Signing Cert name does not comply with signing policy");

  identityManager_->signByCertificate(data, signingCertificateName, wireFormat);
}

shared_ptr<Signature>
KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
{
  Name signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(identityName);

  if (signingCertificateName.size() == 0)
    throw SecurityException("No qualified certificate name found!");

  return identityManager_->signByCertificate(buffer, bufferLength, signingCertificateName);
}

void
KeyChain::verifyData
  (const shared_ptr<Data>& data, const OnVerified& onVerified, const OnVerifyFailed& onVerifyFailed, int stepCount)
{
  _LOG_TRACE("Enter Verify");

  if (policyManager_->requireVerify(*data)) {
    shared_ptr<ValidationRequest> nextStep = policyManager_->checkVerificationPolicy
      (data, stepCount, onVerified, onVerifyFailed);
    if (nextStep)
      face_->expressInterest
        (*nextStep->interest_,
         bind(&KeyChain::onCertificateData, this, _1, _2, nextStep),
         bind(&KeyChain::onCertificateInterestTimeout, this, _1, nextStep->retry_, onVerifyFailed, data, nextStep));
  }
  else if (policyManager_->skipVerifyAndTrust(*data))
    onVerified(data);
  else
    onVerifyFailed(data);
}

void
KeyChain::onCertificateData(const shared_ptr<const Interest> &interest, const shared_ptr<Data> &data, shared_ptr<ValidationRequest> nextStep)
{
  // Try to verify the certificate (data) according to the parameters in nextStep.
  verifyData(data, nextStep->onVerified_, nextStep->onVerifyFailed_, nextStep->stepCount_);
}

void
KeyChain::onCertificateInterestTimeout
  (const shared_ptr<const Interest> &interest, int retry, const OnVerifyFailed& onVerifyFailed, const shared_ptr<Data> &data,
   shared_ptr<ValidationRequest> nextStep)
{
  if (retry > 0)
    // Issue the same expressInterest as in verifyData except decrement retry.
    face_->expressInterest
      (*interest,
       bind(&KeyChain::onCertificateData, this, _1, _2, nextStep),
       bind(&KeyChain::onCertificateInterestTimeout, this, _1, retry - 1, onVerifyFailed, data, nextStep));
  else
    onVerifyFailed(data);
}

}
<commit_msg>security: in key-chain.cpp for bind with _1, if using std::function, need namespace placeholders. Refs #1063.<commit_after>/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#include "../c/util/crypto.h"
#include "../c/encoding/binary-xml-data.h"
#include "../encoding/binary-xml-encoder.hpp"
#include <ndn-cpp/sha256-with-rsa-signature.hpp>
#include "../util/logging.hpp"
#include <ndn-cpp/security/security-exception.hpp>
#include <ndn-cpp/security/policy/policy-manager.hpp>
#include "policy/validation-request.hpp"
#include <ndn-cpp/security/key-chain.hpp>

using namespace std;
using namespace ndn::ptr_lib;
#if NDN_CPP_HAVE_STD_FUNCTION
// In the std library, the placeholders are in a different namespace than boost.
using namespace func_lib::placeholders;
#endif

namespace ndn {

KeyChain::KeyChain(const shared_ptr<IdentityManager>& identityManager, const shared_ptr<PolicyManager>& policyManager)
: identityManager_(identityManager), policyManager_(policyManager), face_(0), maxSteps_(100)
{
}

void
KeyChain::sign(Data& data, const Name& certificateName, WireFormat& wireFormat)
{
  identityManager_->signByCertificate(data, certificateName, wireFormat);
}

shared_ptr<Signature>
KeyChain::sign(const uint8_t* buffer, size_t bufferLength, const Name& certificateName)
{
  return identityManager_->signByCertificate(buffer, bufferLength, certificateName);
}

void
KeyChain::signByIdentity(Data& data, const Name& identityName, WireFormat& wireFormat)
{
  Name signingCertificateName;

  if (identityName.getComponentCount() == 0) {
    Name inferredIdentity = policyManager_->inferSigningIdentity(data.getName());
    if (inferredIdentity.getComponentCount() == 0)
      signingCertificateName = identityManager_->getDefaultCertificateName();
    else
      signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(inferredIdentity);
  }
  else
    signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(identityName);

  if (signingCertificateName.getComponentCount() == 0)
    throw SecurityException("No qualified certificate name found!");

  if (!policyManager_->checkSigningPolicy(data.getName(), signingCertificateName))
    throw SecurityException("Signing Cert name does not comply with signing policy");

  identityManager_->signByCertificate(data, signingCertificateName, wireFormat);
}

shared_ptr<Signature>
KeyChain::signByIdentity(const uint8_t* buffer, size_t bufferLength, const Name& identityName)
{
  Name signingCertificateName = identityManager_->getDefaultCertificateNameForIdentity(identityName);

  if (signingCertificateName.size() == 0)
    throw SecurityException("No qualified certificate name found!");

  return identityManager_->signByCertificate(buffer, bufferLength, signingCertificateName);
}

void
KeyChain::verifyData
  (const shared_ptr<Data>& data, const OnVerified& onVerified, const OnVerifyFailed& onVerifyFailed, int stepCount)
{
  _LOG_TRACE("Enter Verify");

  if (policyManager_->requireVerify(*data)) {
    shared_ptr<ValidationRequest> nextStep = policyManager_->checkVerificationPolicy
      (data, stepCount, onVerified, onVerifyFailed);
    if (nextStep)
      face_->expressInterest
        (*nextStep->interest_,
         bind(&KeyChain::onCertificateData, this, _1, _2, nextStep),
         bind(&KeyChain::onCertificateInterestTimeout, this, _1, nextStep->retry_, onVerifyFailed, data, nextStep));
  }
  else if (policyManager_->skipVerifyAndTrust(*data))
    onVerified(data);
  else
    onVerifyFailed(data);
}

void
KeyChain::onCertificateData(const shared_ptr<const Interest> &interest, const shared_ptr<Data> &data, shared_ptr<ValidationRequest> nextStep)
{
  // Try to verify the certificate (data) according to the parameters in nextStep.
  verifyData(data, nextStep->onVerified_, nextStep->onVerifyFailed_, nextStep->stepCount_);
}

void
KeyChain::onCertificateInterestTimeout
  (const shared_ptr<const Interest> &interest, int retry, const OnVerifyFailed& onVerifyFailed, const shared_ptr<Data> &data,
   shared_ptr<ValidationRequest> nextStep)
{
  if (retry > 0)
    // Issue the same expressInterest as in verifyData except decrement retry.
    face_->expressInterest
      (*interest,
       bind(&KeyChain::onCertificateData, this, _1, _2, nextStep),
       bind(&KeyChain::onCertificateInterestTimeout, this, _1, retry - 1, onVerifyFailed, data, nextStep));
  else
    onVerifyFailed(data);
}

}
<|endoftext|>