<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <vector>

#include "SymbolTable.hpp"
#include "Options.hpp"
#include "Type.hpp"
#include "FunctionContext.hpp"

#include "mtac/inlining.hpp"

using namespace eddic;

std::size_t size_of(std::shared_ptr<mtac::Function> function){
    std::size_t size = 0;

    for(auto block : function->getBasicBlocks()){
        size += block->statements.size();
    }

    return size;
}

typedef std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<Variable>> VariableClones;
typedef std::unordered_map<std::shared_ptr<mtac::BasicBlock>, std::shared_ptr<mtac::BasicBlock>> BBClones;

template<typename Value>
void update_usage(VariableClones& clones, Value& value){
    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&value)){
        if(clones.find(*ptr) != clones.end()){
            value = clones[*ptr];
        }
    }
}

template<typename Opt>
void update_usage_optional(VariableClones& clones, Opt& opt){
    if(opt){
        update_usage(clones, *opt);
    }
}

void update_usages(VariableClones& clones, mtac::Statement& statement){
    if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
        auto quadruple = *ptr;

        if(clones.find(quadruple->result) != clones.end()){
            quadruple->result = clones[quadruple->result];
        }

        update_usage_optional(clones, quadruple->arg1);
        update_usage_optional(clones, quadruple->arg2);
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Param>>(&statement)){
        auto param = *ptr;

        update_usage(clones, param->arg);
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
        auto if_ = *ptr;

        update_usage(clones, if_->arg1);
        update_usage_optional(clones, if_->arg2);
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
        auto if_ = *ptr;

        update_usage(clones, if_->arg1);
        update_usage_optional(clones, if_->arg2);
    }
}

void update_usages(BBClones& clones, mtac::Statement& statement){
    if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
        auto if_ = *ptr;

        if(clones.find(if_->block) != clones.end()){
            if_->block = clones[if_->block];
        }
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
        auto if_ = *ptr;

        if(clones.find(if_->block) != clones.end()){
            if_->block = clones[if_->block];
        }
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Goto>>(&statement)){
        auto goto_ = *ptr;

        if(clones.find(goto_->block) != clones.end()){
            goto_->block = clones[goto_->block];
        }
    }
}

void clone(std::vector<mtac::Statement>& sources, std::vector<mtac::Statement>& destination){
    for(auto& statement : sources){
        if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
            auto quadruple = *ptr;

            auto copy = std::make_shared<mtac::Quadruple>();

            copy->result = quadruple->result;
            copy->arg1 = quadruple->arg1;
            copy->arg2 = quadruple->arg2;
            copy->op = quadruple->op;

            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Param>>(&statement)){
            auto param = *ptr;

            auto copy = std::make_shared<mtac::Param>();

            copy->arg = param->arg;
            copy->param = param->param;
            copy->std_param = param->std_param;
            copy->function = param->function;
            copy->address = param->address;
            copy->memberNames = param->memberNames;

            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
            auto if_ = *ptr;

            auto copy = std::make_shared<mtac::IfFalse>();

            copy->op = if_->op;
            copy->arg1 = if_->arg1;
            copy->arg2 = if_->arg2;
            copy->label = if_->label;
            copy->block = if_->block;

            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
            auto if_ = *ptr;

            auto copy = std::make_shared<mtac::If>();

            copy->op = if_->op;
            copy->arg1 = if_->arg1;
            copy->arg2 = if_->arg2;
            copy->label = if_->label;
            copy->block = if_->block;

            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Goto>>(&statement)){
            auto goto_ = *ptr;

            auto copy = std::make_shared<mtac::Goto>(goto_->label, goto_->type);
            copy->block = goto_->block;
            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Call>>(&statement)){
            auto call = *ptr;

            destination.push_back(std::make_shared<mtac::Call>(call->function, call->functionDefinition, call->return_, call->return2_));
        } else if(auto* ptr = boost::get<std::string>(&statement)){
            destination.push_back(*ptr);
        }

        //No need to copy NOP
    }
}

bool mtac::inline_functions(std::shared_ptr<mtac::Program> program){
    if(option_defined("fno-inline")){
        return false;
    }

    bool optimized = false;

    std::vector<std::shared_ptr<mtac::Function>> inlined;

    for(auto function : program->functions){
        //The main function cannot be inlined
        if(function->getName() == "main"){
            continue;
        }

        //function called once
        if(symbols.referenceCount(function->getName()) == 1){
            inlined.push_back(function);
        } else {
            auto size = size_of(function);

            //Inline little functions
            if(size < 10){
                inlined.push_back(function);
            }
        }
    }

    for(auto source_function : inlined){
        auto source_definition = source_function->definition;

        for(auto dest_function : program->functions){
            if(dest_function == source_function){
                continue;
            }

            auto bit = dest_function->getBasicBlocks().begin();
            auto bend = dest_function->getBasicBlocks().end();

            while(bit != bend){
                auto basic_block = *bit;

                auto it = basic_block->statements.begin();
                auto end = basic_block->statements.end();

                while(it != end){
                    auto statement = *it;

                    if(auto* ptr = boost::get<std::shared_ptr<mtac::Call>>(&statement)){
                        auto call = *ptr;

                        if(call->functionDefinition == source_definition){
                            //Handle parameters
                            if(source_definition->parameters.size() > 0){
                                ++it;
                                continue;//TODO Temporary
                            }

                            optimized = true;

                            std::cout << "inline " << source_definition->mangledName << " in function " << dest_function->definition->mangledName << std::endl;

                            VariableClones variable_clones;
                            for(auto variable_pair : *source_definition->context){
                                auto variable = variable_pair.second;
                                variable_clones[variable] = dest_function->definition->context->newVariable(variable);
                            }

                            BBClones bb_clones;

                            auto saved_bit = bit;

                            std::size_t cloned_bb = 0;

                            for(auto block : source_function->getBasicBlocks()){
                                //Copy all basic blocks except ENTRY and EXIT
                                if(block->index >= 0){
                                    auto new_bb = std::make_shared<mtac::BasicBlock>(dest_function->getBasicBlocks().size() + 1);
                                    new_bb->context = block->context;
                                    clone(block->statements, new_bb->statements);

                                    bb_clones[block] = new_bb;

                                    ++cloned_bb;

                                    bit = dest_function->getBasicBlocks().insert(bit, new_bb);
                                    bend = dest_function->getBasicBlocks().end();

                                    ++bit;
                                }
                            }

                            bit = saved_bit;

                            while(cloned_bb > 0){
                                auto new_bb = *bit;

                                auto ssit = new_bb->statements.begin();
                                auto ssend = new_bb->statements.end();

                                while(ssit != ssend){
                                    update_usages(variable_clones, *ssit);
                                    update_usages(bb_clones, *ssit);

                                    if(auto* ret_ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&*ssit)){
                                        auto quadruple = *ret_ptr;

                                        if(quadruple->op == mtac::Operator::RETURN){
                                            if(!call->return_){
                                                //If the caller does not care about the return value, return has no effect
                                                ssit = new_bb->statements.erase(it);
                                                ssend = new_bb->statements.end();
                                            } else {
                                                mtac::Operator op;
                                                if(source_definition->returnType == FLOAT){
                                                    op = mtac::Operator::FASSIGN;
                                                } else if(source_definition->returnType->is_pointer()){
                                                    op = mtac::Operator::PASSIGN;
                                                } else {
                                                    op = mtac::Operator::ASSIGN;
                                                }

                                                if(call->return2_){
                                                    auto new_quadruple = std::make_shared<mtac::Quadruple>(call->return2_, *quadruple->arg2, op);

                                                    ssit = new_bb->statements.insert(it, new_quadruple);
                                                    ssend = new_bb->statements.end();
                                                }

                                                quadruple->op = op;
                                                quadruple->result = call->return_;
                                                quadruple->arg2.reset();
                                            }
                                        }
                                    }

                                    ++ssit;
                                }

                                --cloned_bb;
                                ++bit;
                            }

                            bit = saved_bit;

                            it = basic_block->statements.erase(it);
                            end = basic_block->statements.end();

                            continue;
                        }
                    }

                    ++it;
                }

                ++bit;
            }
        }
    }

    return optimized;
}
<commit_msg>Update the usages on the good basic blocks<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <vector>

#include "SymbolTable.hpp"
#include "Options.hpp"
#include "Type.hpp"
#include "FunctionContext.hpp"

#include "mtac/inlining.hpp"

using namespace eddic;

std::size_t size_of(std::shared_ptr<mtac::Function> function){
    std::size_t size = 0;

    for(auto block : function->getBasicBlocks()){
        size += block->statements.size();
    }

    return size;
}

typedef std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<Variable>> VariableClones;
typedef std::unordered_map<std::shared_ptr<mtac::BasicBlock>, std::shared_ptr<mtac::BasicBlock>> BBClones;

template<typename Value>
void update_usage(VariableClones& clones, Value& value){
    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&value)){
        if(clones.find(*ptr) != clones.end()){
            value = clones[*ptr];
        }
    }
}

template<typename Opt>
void update_usage_optional(VariableClones& clones, Opt& opt){
    if(opt){
        update_usage(clones, *opt);
    }
}

void update_usages(VariableClones& clones, mtac::Statement& statement){
    if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
        auto quadruple = *ptr;

        if(clones.find(quadruple->result) != clones.end()){
            quadruple->result = clones[quadruple->result];
        }

        update_usage_optional(clones, quadruple->arg1);
        update_usage_optional(clones, quadruple->arg2);
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Param>>(&statement)){
        auto param = *ptr;

        update_usage(clones, param->arg);
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
        auto if_ = *ptr;

        update_usage(clones, if_->arg1);
        update_usage_optional(clones, if_->arg2);
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
        auto if_ = *ptr;

        update_usage(clones, if_->arg1);
        update_usage_optional(clones, if_->arg2);
    }
}

void update_usages(BBClones& clones, mtac::Statement& statement){
    if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
        auto if_ = *ptr;

        if(clones.find(if_->block) != clones.end()){
            if_->block = clones[if_->block];
        }
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
        auto if_ = *ptr;

        if(clones.find(if_->block) != clones.end()){
            if_->block = clones[if_->block];
        }
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Goto>>(&statement)){
        auto goto_ = *ptr;

        if(clones.find(goto_->block) != clones.end()){
            goto_->block = clones[goto_->block];
        }
    }
}

void clone(std::vector<mtac::Statement>& sources, std::vector<mtac::Statement>& destination){
    for(auto& statement : sources){
        if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
            auto quadruple = *ptr;

            auto copy = std::make_shared<mtac::Quadruple>();

            copy->result = quadruple->result;
            copy->arg1 = quadruple->arg1;
            copy->arg2 = quadruple->arg2;
            copy->op = quadruple->op;

            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Param>>(&statement)){
            auto param = *ptr;

            auto copy = std::make_shared<mtac::Param>();

            copy->arg = param->arg;
            copy->param = param->param;
            copy->std_param = param->std_param;
            copy->function = param->function;
            copy->address = param->address;
            copy->memberNames = param->memberNames;

            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
            auto if_ = *ptr;

            auto copy = std::make_shared<mtac::IfFalse>();

            copy->op = if_->op;
            copy->arg1 = if_->arg1;
            copy->arg2 = if_->arg2;
            copy->label = if_->label;
            copy->block = if_->block;

            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
            auto if_ = *ptr;

            auto copy = std::make_shared<mtac::If>();

            copy->op = if_->op;
            copy->arg1 = if_->arg1;
            copy->arg2 = if_->arg2;
            copy->label = if_->label;
            copy->block = if_->block;

            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Goto>>(&statement)){
            auto goto_ = *ptr;

            auto copy = std::make_shared<mtac::Goto>(goto_->label, goto_->type);
            copy->block = goto_->block;
            destination.push_back(copy);
        } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Call>>(&statement)){
            auto call = *ptr;

            destination.push_back(std::make_shared<mtac::Call>(call->function, call->functionDefinition, call->return_, call->return2_));
        } else if(auto* ptr = boost::get<std::string>(&statement)){
            destination.push_back(*ptr);
        }

        //No need to copy NOP
    }
}

bool mtac::inline_functions(std::shared_ptr<mtac::Program> program){
    if(option_defined("fno-inline")){
        return false;
    }

    bool optimized = false;

    std::vector<std::shared_ptr<mtac::Function>> inlined;

    for(auto function : program->functions){
        //The main function cannot be inlined
        if(function->getName() == "main"){
            continue;
        }

        //function called once
        if(symbols.referenceCount(function->getName()) == 1){
            inlined.push_back(function);
        } else {
            auto size = size_of(function);

            //Inline little functions
            if(size < 10){
                inlined.push_back(function);
            }
        }
    }

    for(auto source_function : inlined){
        auto source_definition = source_function->definition;

        for(auto dest_function : program->functions){
            if(dest_function == source_function){
                continue;
            }

            auto bit = dest_function->getBasicBlocks().begin();
            auto bend = dest_function->getBasicBlocks().end();

            while(bit != bend){
                auto basic_block = *bit;

                auto it = basic_block->statements.begin();
                auto end = basic_block->statements.end();

                while(it != end){
                    auto statement = *it;

                    if(auto* ptr = boost::get<std::shared_ptr<mtac::Call>>(&statement)){
                        auto call = *ptr;

                        if(call->functionDefinition == source_definition){
                            //Handle parameters
                            if(source_definition->parameters.size() > 0){
                                ++it;
                                continue;//TODO Temporary
                            }

                            //optimized = true;

                            std::cout << "inline " << source_definition->mangledName << " in function " << dest_function->definition->mangledName << std::endl;

                            VariableClones variable_clones;
                            for(auto variable_pair : *source_definition->context){
                                auto variable = variable_pair.second;
                                variable_clones[variable] = dest_function->definition->context->newVariable(variable);
                            }

                            BBClones bb_clones;

                            auto saved_bit = bit;

                            std::size_t cloned_bb = 0;

                            for(auto block : source_function->getBasicBlocks()){
                                //Copy all basic blocks except ENTRY and EXIT
                                if(block->index >= 0){
                                    auto new_bb = std::make_shared<mtac::BasicBlock>(dest_function->getBasicBlocks().size() + 1);
                                    new_bb->context = block->context;
                                    clone(block->statements, new_bb->statements);

                                    bb_clones[block] = new_bb;

                                    ++cloned_bb;

                                    bit = dest_function->getBasicBlocks().insert(bit, new_bb);
                                    bend = dest_function->getBasicBlocks().end();

                                    ++bit;
                                }
                            }

                            bit = saved_bit;
                            --bit;

                            while(cloned_bb > 0){
                                auto new_bb = *bit;

                                auto ssit = new_bb->statements.begin();
                                auto ssend = new_bb->statements.end();

                                while(ssit != ssend){
                                    update_usages(variable_clones, *ssit);
                                    update_usages(bb_clones, *ssit);

                                    if(auto* ret_ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&*ssit)){
                                        auto quadruple = *ret_ptr;

                                        if(quadruple->op == mtac::Operator::RETURN){
                                            if(!call->return_){
                                                //If the caller does not care about the return value, return has no effect
                                                ssit = new_bb->statements.erase(it);
                                                ssend = new_bb->statements.end();
                                            } else {
                                                mtac::Operator op;
                                                if(source_definition->returnType == FLOAT){
                                                    op = mtac::Operator::FASSIGN;
                                                } else if(source_definition->returnType->is_pointer()){
                                                    op = mtac::Operator::PASSIGN;
                                                } else {
                                                    op = mtac::Operator::ASSIGN;
                                                }

                                                if(call->return2_){
                                                    auto new_quadruple = std::make_shared<mtac::Quadruple>(call->return2_, *quadruple->arg2, op);

                                                    ssit = new_bb->statements.insert(it, new_quadruple);
                                                    ssend = new_bb->statements.end();
                                                }

                                                quadruple->op = op;
                                                quadruple->result = call->return_;
                                                quadruple->arg2.reset();
                                            }
                                        }
                                    }

                                    ++ssit;
                                }

                                --cloned_bb;
                                --bit;
                            }

                            bit = saved_bit;

                            it = basic_block->statements.erase(it);
                            end = basic_block->statements.end();

                            continue;
                        }
                    }

                    ++it;
                }

                ++bit;
            }
        }
    }

    return optimized;
}
<|endoftext|>


<commit_before>#include "GUI.hpp"

#include <string>
#include <vector>

#include <QMessageBox>
#include <QAction>
#include <QCloseEvent>
#include <QFontDatabase>
#include "Game.hpp"

#include "NewGameDialog.hpp"
#include "VirtualView.hpp"
#include "AugmentedView.hpp"

namespace Go_GUI {

GUI::GUI(QWidget *parent) : QMainWindow(parent), go_game(nullptr)
{
    ui_main.setupUi(this);

    texture_path = "res/textures/";
    QApplication::setWindowIcon(QIcon(QPixmap(texture_path + "augmented_logo_transparent_icon.png")));
    augmented_logo = QImage(texture_path + "augmented_logo.png");

    virtual_view = new VirtualView(this);
    augmented_view = new AugmentedView(this);

    whitebasket_pixmap = QPixmap(texture_path + "white_basket.png");
    blackbasket_pixmap = QPixmap(texture_path + "black_basket.png");
    closedbasket_pixmap = QPixmap(texture_path + "Closed_basket.png");
    gotable_pixmap = QPixmap(texture_path + "go_table.png");
    if (blackbasket_pixmap.isNull() || whitebasket_pixmap.isNull() || closedbasket_pixmap.isNull() || gotable_pixmap.isNull())
        QMessageBox::critical(this, "GUI element not found", QString("White and/or black basket textures not found!\n searched relative to exe in: " + texture_path));

    // loading font
    QFontDatabase fontDatabase;
    QString font_path = "res/fonts/SHOJUMARU-REGULAR.TTF";
    if (fontDatabase.addApplicationFont(font_path) == -1)
        QMessageBox::critical(this, "Font not found", QString("Shojumaru font was not found!\n searched relative to exe in: " + font_path));

    // connections
    connect(ui_main.open_action,		&QAction::triggered,	this, &GUI::slot_MenuOpen);
    connect(ui_main.save_action,		&QAction::triggered,	this, &GUI::slot_MenuSave);
    connect(ui_main.exit_action,		&QAction::triggered,	this, &QWidget::close);
    connect(ui_main.info_action,		&QAction::triggered,	this, &GUI::slot_MenuInfo);
    connect(ui_main.automatic_action,   &QAction::triggered,	this, &GUI::slot_BoardDetectionAutomatically);
    connect(ui_main.manually_action,	&QAction::triggered,	this, &GUI::slot_BoardDetectionManually);
    connect(ui_main.virtual_game_mode_action,	&QAction::triggered, this, &GUI::slot_ToggleVirtualGameMode);
    connect(this,	&GUI::signal_setVirtualGameMode, this->virtual_view, &VirtualView::slot_setVirtualGameMode);
    connect(ui_main.viewswitch_button,	&QPushButton::clicked,	this, &GUI::slot_ViewSwitch);
    connect(ui_main.newgame_button,	    &QPushButton::clicked,	this, &GUI::slot_ButtonNewGame);
    connect(ui_main.pass_button,	    &QPushButton::clicked,	this, &GUI::slot_ButtonPass);
    connect(ui_main.resign_button,	    &QPushButton::clicked,	this, &GUI::slot_ButtonResign);
    connect(this->virtual_view,	        &VirtualView::signal_virtualViewplayMove,	this, &GUI::slot_passOnVirtualViewPlayMove);
    connect(ui_main.scannerdebugimage_action,	&QAction::triggered,	this, &GUI::slot_toggleScannerDebugImage);

    // setting initial values
    this->init();
}

void GUI::init(){
    this->setWindowTitle("Augmented Go");
    this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // Attaching augmented view to big container
    augmented_view->setParent(ui_main.big_container);
    augmented_view->rescaleImage(ui_main.big_container->size());
    ui_main.big_container->setToolTip("augmented view");
    augmented_view->show();

    // Attaching virtual view to small container
    virtual_view->setParent(ui_main.small_container);
    ui_main.small_container->setToolTip("virtual view");
    virtual_view->show();

    ui_main.white_basket->setPixmap(closedbasket_pixmap);
    ui_main.black_basket->setPixmap(closedbasket_pixmap);
    ui_main.go_table_label->setPixmap(gotable_pixmap);

    ui_main.capturedwhite_label->setText(QString());
    ui_main.capturedblack_label->setText(QString());

    emit signal_setVirtualGameMode(ui_main.virtual_game_mode_action->isChecked());
}

void GUI::setPlayerLabels(QString blackplayer_name, QString whiteplayer_name){
    ui_main.blackplayer_label->setText(blackplayer_name);
    ui_main.whiteplayer_label->setText(whiteplayer_name);
}

//////////
//Private Slots
//////////

void GUI::slot_ButtonNewGame(){
    NewGameDialog* newgame = new NewGameDialog(this);
    newgame->exec();
}

void GUI::slot_ButtonResign(){
    if (QMessageBox::question(this, "Resign", "Do you really want to admit defeat?") == QMessageBox::Yes)
        emit signal_resign();
}

void GUI::slot_ButtonPass(){
    if (QMessageBox::question(this, "Pass", "Do you really want to pass?") == QMessageBox::Yes)
        emit signal_pass();
}

void GUI::slot_ViewSwitch(){
    if (ui_main.big_container->toolTip() == "virtual view"){

        // switching augmented view to big container
        augmented_view->setParent(ui_main.big_container);
        augmented_view->rescaleImage(ui_main.big_container->size());
        ui_main.big_container->setToolTip("augmented view");
        augmented_view->show();		// when changing parent, it gets invisible -> show again! -.- !!

        // new style
        virtual_view->setParent(ui_main.small_container);
        virtual_view->createAndSetScene(ui_main.small_container->size(), &(go_game->getBoard()));
        ui_main.small_container->setToolTip("virtual view");
        virtual_view->show();

    }
    else if (ui_main.big_container->toolTip() == "augmented view"){
        // switching augmented view to small container
        augmented_view->setParent(ui_main.small_container);
        augmented_view->rescaleImage(ui_main.small_container->size());
        ui_main.small_container->setToolTip("augmented view");
        augmented_view->show();		// when changing parent, it gets invisible -> show again! -.- !!

        virtual_view->setParent(ui_main.big_container);
        virtual_view->createAndSetScene(ui_main.big_container->size(), &(go_game->getBoard()));
        ui_main.big_container->setToolTip("virtual view");
        virtual_view->show();
    }
}

void GUI::slot_MenuOpen(){
    QString selfilter = tr("SGF (*.sgf)");
    QString fileName = QFileDialog::getOpenFileName(
        this,
        "open sgf-file",
        NULL,
        tr("SGF (*.sgf)" ),
        &selfilter
    );

    if (!fileName.isNull()){
        // TODO ask if user wants to save the current game!
        emit signal_openGame(fileName);
    }
}

void GUI::slot_MenuSave(){
    QString selfilter = tr("SGF (*.sgf)");
    QString fileName = QFileDialog::getSaveFileName(
        this,
        "save sgf-file",
        NULL,
        tr("SGF (*.sgf)" ),
        &selfilter
    );

    if (!fileName.isNull())
        emit signal_saveGame(fileName, ui_main.blackplayer_label->text(), ui_main.whiteplayer_label->text(), this->game_name);
}

void GUI::slot_MenuInfo(){
    // Appliction Info
    std::string output = "Augmented Go - Interactive Game of Go as Augmented Reality Application\n\n\n";

    // Build date and time
    output += "This build of Augmented Go was compiled at " __DATE__ ", " __TIME__ ".\n";

    // Copyright
    std::string year = __DATE__;
    year = year.substr(year.find_last_of(" "));	// deleting day and month
    output += "Copyright " + year + "\n";

    // Licence
    output += "\nThis software is released under the \"MIT License\".\n"
        "See the file LICENSE for full license and copying terms.\n";

    // Final InfoBox
    QMessageBox::about(this, "Info", output.c_str());
}

void GUI::slot_BoardDetectionManually() {
    emit signal_boardDetectionManually();
}

void GUI::slot_BoardDetectionAutomatically() {
    emit signal_boardDetectionAutomatically();
}

void GUI::slot_ToggleVirtualGameMode() {
    // if in augmented mode -> switch to virtual
    if (ui_main.virtual_game_mode_action->isChecked()){
        this->setWindowTitle("Augmented Go - Virtual Mode");

        // change virtual view to big container
        if (ui_main.big_container->toolTip() != "virtual view")
            this->slot_ViewSwitch();

        emit signal_setVirtualGameMode(true);
        slot_newImage(augmented_logo);
    }

    // if in virtual mode -> switch to augmented
    else{
        this->setWindowTitle("Augmented Go");

        // change augmented view to big container
        if (ui_main.big_container->toolTip() != "augmented view")
            this->slot_ViewSwitch();
        augmented_view->setStyleSheet("background-color: black");

        emit signal_setVirtualGameMode(false);
    }
}

void GUI::slot_passOnVirtualViewPlayMove(const int x, const int y){
    emit this->signal_playMove(x, y);
}

void GUI::slot_toggleScannerDebugImage()
{
    if (ui_main.scannerdebugimage_action->isChecked())
        emit signal_setScannerDebugImage(true);
    else
        emit signal_setScannerDebugImage(false);
}

//////////
//Public Slots
//////////

void GUI::slot_newImage(QImage image) {
        printf(">>> New Image arrived! '%d x %d' -- Format: %d <<<\n", image.width(), image.height(), image.format());
        augmented_view->setImage(image);
        augmented_view->rescaleImage(augmented_view->parentWidget()->size());
    }

void GUI::slot_newGameData(const GoBackend::Game* game) {
    // update internal pointer if the board has been changed
    if (go_game != game)
        go_game = game;

    auto& board = go_game->getBoard();

    auto current_player = board.ToPlay();

    // Updating basket pictures
    switch (current_player) {
    case SG_WHITE:
        ui_main.white_basket->setPixmap(whitebasket_pixmap);
        ui_main.black_basket->setPixmap(closedbasket_pixmap);
        break;
    case SG_BLACK:
        ui_main.white_basket->setPixmap(closedbasket_pixmap);
        ui_main.black_basket->setPixmap(blackbasket_pixmap);
        break;
    default:
        assert(false);
        break;
    }

    // Updating Game-Settings
    ui_main.movenumber_label->setText(QString::number(board.MoveNumber()));
    ui_main.kominumber_label->setText(QString::number(board.Rules().Komi().ToFloat()));
    ui_main.handicapnumber_label->setText(QString::number(board.Rules().Handicap()));
    ui_main.capturedwhite_label->setText(QString::number(board.NumPrisoners(SG_WHITE)));
    ui_main.capturedblack_label->setText(QString::number(board.NumPrisoners(SG_BLACK)));

    // refresh virtual view
    if (ui_main.big_container->toolTip() == "virtual view")
        virtual_view->createAndSetScene(ui_main.big_container->size(), &board);

    else if (ui_main.big_container->toolTip() == "augmented view")
        virtual_view->createAndSetScene(ui_main.small_container->size(), &board);

    printf(">>> New Game data! <<<\n");
}

void GUI::slot_showFinishedGameResults(QString result){
    QMessageBox::information(this, "Game results", result);
    auto answer = QMessageBox::question(this, "New Game?", "Do you want to start a new game?");
    if (answer == QMessageBox::Yes)
        this->slot_ButtonNewGame();
}

void GUI::slot_setupNewGame(QString game_name, QString blackplayer_name, QString whiteplayer_name, float komi){

    // emit to backend that gui wants to set up a new game!
    auto rules = GoRules(0, GoKomi(komi), true, true);
    emit signal_newGame(rules);

    // Setting up new names for players
    ui_main.gamename_label->setText(game_name);
    ui_main.blackplayer_label->setText(blackplayer_name);
    ui_main.whiteplayer_label->setText(whiteplayer_name);
    ui_main.kominumber_label->setText(QString::number(komi));
    ui_main.handicapnumber_label->setText(QString::number(0));
}

///////////
//Events
///////////

void GUI::closeEvent(QCloseEvent *event){

    // If at least one move was was done
    // TODO If game loaded -> move number greater than start number!
    int answer = 0;

    // if at least one move was made -> ask if user wants to save
    bool saveable = ui_main.movenumber_label->text().toInt() > 0;

    if (saveable)
        answer = QMessageBox::question(this, "Save?", "Do you want to save before quit?", "Save", "Don't Save", "Cancel");
    else
        answer = QMessageBox::question(this, "Quit?", "Do you really want to quit?", "Quit", "Cancel");

    if(answer == 0 && saveable){
        this->slot_MenuSave();
        emit stop_backend_thread();
        event->accept();
    }
    else if((answer == 1 && saveable)
        || (answer == 0 && !saveable)){
        emit stop_backend_thread();
        event->accept();
    }
    else
        event->ignore();
}

} // namespace Go_GUI<commit_msg>refs #104 changed text slightly from "...quit" to "...quitting"<commit_after>#include "GUI.hpp"

#include <string>
#include <vector>

#include <QMessageBox>
#include <QAction>
#include <QCloseEvent>
#include <QFontDatabase>
#include "Game.hpp"

#include "NewGameDialog.hpp"
#include "VirtualView.hpp"
#include "AugmentedView.hpp"

namespace Go_GUI {

GUI::GUI(QWidget *parent) : QMainWindow(parent), go_game(nullptr)
{
    ui_main.setupUi(this);

    texture_path = "res/textures/";
    QApplication::setWindowIcon(QIcon(QPixmap(texture_path + "augmented_logo_transparent_icon.png")));
    augmented_logo = QImage(texture_path + "augmented_logo.png");

    virtual_view = new VirtualView(this);
    augmented_view = new AugmentedView(this);

    whitebasket_pixmap = QPixmap(texture_path + "white_basket.png");
    blackbasket_pixmap = QPixmap(texture_path + "black_basket.png");
    closedbasket_pixmap = QPixmap(texture_path + "Closed_basket.png");
    gotable_pixmap = QPixmap(texture_path + "go_table.png");
    if (blackbasket_pixmap.isNull() || whitebasket_pixmap.isNull() || closedbasket_pixmap.isNull() || gotable_pixmap.isNull())
        QMessageBox::critical(this, "GUI element not found", QString("White and/or black basket textures not found!\n searched relative to exe in: " + texture_path));

    // loading font
    QFontDatabase fontDatabase;
    QString font_path = "res/fonts/SHOJUMARU-REGULAR.TTF";
    if (fontDatabase.addApplicationFont(font_path) == -1)
        QMessageBox::critical(this, "Font not found", QString("Shojumaru font was not found!\n searched relative to exe in: " + font_path));

    // connections
    connect(ui_main.open_action,		&QAction::triggered,	this, &GUI::slot_MenuOpen);
    connect(ui_main.save_action,		&QAction::triggered,	this, &GUI::slot_MenuSave);
    connect(ui_main.exit_action,		&QAction::triggered,	this, &QWidget::close);
    connect(ui_main.info_action,		&QAction::triggered,	this, &GUI::slot_MenuInfo);
    connect(ui_main.automatic_action,   &QAction::triggered,	this, &GUI::slot_BoardDetectionAutomatically);
    connect(ui_main.manually_action,	&QAction::triggered,	this, &GUI::slot_BoardDetectionManually);
    connect(ui_main.virtual_game_mode_action,	&QAction::triggered, this, &GUI::slot_ToggleVirtualGameMode);
    connect(this,	&GUI::signal_setVirtualGameMode, this->virtual_view, &VirtualView::slot_setVirtualGameMode);
    connect(ui_main.viewswitch_button,	&QPushButton::clicked,	this, &GUI::slot_ViewSwitch);
    connect(ui_main.newgame_button,	    &QPushButton::clicked,	this, &GUI::slot_ButtonNewGame);
    connect(ui_main.pass_button,	    &QPushButton::clicked,	this, &GUI::slot_ButtonPass);
    connect(ui_main.resign_button,	    &QPushButton::clicked,	this, &GUI::slot_ButtonResign);
    connect(this->virtual_view,	        &VirtualView::signal_virtualViewplayMove,	this, &GUI::slot_passOnVirtualViewPlayMove);
    connect(ui_main.scannerdebugimage_action,	&QAction::triggered,	this, &GUI::slot_toggleScannerDebugImage);

    // setting initial values
    this->init();
}

void GUI::init(){
    this->setWindowTitle("Augmented Go");
    this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // Attaching augmented view to big container
    augmented_view->setParent(ui_main.big_container);
    augmented_view->rescaleImage(ui_main.big_container->size());
    ui_main.big_container->setToolTip("augmented view");
    augmented_view->show();

    // Attaching virtual view to small container
    virtual_view->setParent(ui_main.small_container);
    ui_main.small_container->setToolTip("virtual view");
    virtual_view->show();

    ui_main.white_basket->setPixmap(closedbasket_pixmap);
    ui_main.black_basket->setPixmap(closedbasket_pixmap);
    ui_main.go_table_label->setPixmap(gotable_pixmap);

    ui_main.capturedwhite_label->setText(QString());
    ui_main.capturedblack_label->setText(QString());

    emit signal_setVirtualGameMode(ui_main.virtual_game_mode_action->isChecked());
}

void GUI::setPlayerLabels(QString blackplayer_name, QString whiteplayer_name){
    ui_main.blackplayer_label->setText(blackplayer_name);
    ui_main.whiteplayer_label->setText(whiteplayer_name);
}

//////////
//Private Slots
//////////

void GUI::slot_ButtonNewGame(){
    NewGameDialog* newgame = new NewGameDialog(this);
    newgame->exec();
}

void GUI::slot_ButtonResign(){
    if (QMessageBox::question(this, "Resign", "Do you really want to admit defeat?") == QMessageBox::Yes)
        emit signal_resign();
}

void GUI::slot_ButtonPass(){
    if (QMessageBox::question(this, "Pass", "Do you really want to pass?") == QMessageBox::Yes)
        emit signal_pass();
}

void GUI::slot_ViewSwitch(){
    if (ui_main.big_container->toolTip() == "virtual view"){

        // switching augmented view to big container
        augmented_view->setParent(ui_main.big_container);
        augmented_view->rescaleImage(ui_main.big_container->size());
        ui_main.big_container->setToolTip("augmented view");
        augmented_view->show();		// when changing parent, it gets invisible -> show again! -.- !!

        // new style
        virtual_view->setParent(ui_main.small_container);
        virtual_view->createAndSetScene(ui_main.small_container->size(), &(go_game->getBoard()));
        ui_main.small_container->setToolTip("virtual view");
        virtual_view->show();

    }
    else if (ui_main.big_container->toolTip() == "augmented view"){
        // switching augmented view to small container
        augmented_view->setParent(ui_main.small_container);
        augmented_view->rescaleImage(ui_main.small_container->size());
        ui_main.small_container->setToolTip("augmented view");
        augmented_view->show();		// when changing parent, it gets invisible -> show again! -.- !!

        virtual_view->setParent(ui_main.big_container);
        virtual_view->createAndSetScene(ui_main.big_container->size(), &(go_game->getBoard()));
        ui_main.big_container->setToolTip("virtual view");
        virtual_view->show();
    }
}

void GUI::slot_MenuOpen(){
    QString selfilter = tr("SGF (*.sgf)");
    QString fileName = QFileDialog::getOpenFileName(
        this,
        "open sgf-file",
        NULL,
        tr("SGF (*.sgf)" ),
        &selfilter
    );

    if (!fileName.isNull()){
        // TODO ask if user wants to save the current game!
        emit signal_openGame(fileName);
    }
}

void GUI::slot_MenuSave(){
    QString selfilter = tr("SGF (*.sgf)");
    QString fileName = QFileDialog::getSaveFileName(
        this,
        "save sgf-file",
        NULL,
        tr("SGF (*.sgf)" ),
        &selfilter
    );

    if (!fileName.isNull())
        emit signal_saveGame(fileName, ui_main.blackplayer_label->text(), ui_main.whiteplayer_label->text(), this->game_name);
}

void GUI::slot_MenuInfo(){
    // Appliction Info
    std::string output = "Augmented Go - Interactive Game of Go as Augmented Reality Application\n\n\n";

    // Build date and time
    output += "This build of Augmented Go was compiled at " __DATE__ ", " __TIME__ ".\n";

    // Copyright
    std::string year = __DATE__;
    year = year.substr(year.find_last_of(" "));	// deleting day and month
    output += "Copyright " + year + "\n";

    // Licence
    output += "\nThis software is released under the \"MIT License\".\n"
        "See the file LICENSE for full license and copying terms.\n";

    // Final InfoBox
    QMessageBox::about(this, "Info", output.c_str());
}

void GUI::slot_BoardDetectionManually() {
    emit signal_boardDetectionManually();
}

void GUI::slot_BoardDetectionAutomatically() {
    emit signal_boardDetectionAutomatically();
}

void GUI::slot_ToggleVirtualGameMode() {
    // if in augmented mode -> switch to virtual
    if (ui_main.virtual_game_mode_action->isChecked()){
        this->setWindowTitle("Augmented Go - Virtual Mode");

        // change virtual view to big container
        if (ui_main.big_container->toolTip() != "virtual view")
            this->slot_ViewSwitch();

        emit signal_setVirtualGameMode(true);
        slot_newImage(augmented_logo);
    }

    // if in virtual mode -> switch to augmented
    else{
        this->setWindowTitle("Augmented Go");

        // change augmented view to big container
        if (ui_main.big_container->toolTip() != "augmented view")
            this->slot_ViewSwitch();
        augmented_view->setStyleSheet("background-color: black");

        emit signal_setVirtualGameMode(false);
    }
}

void GUI::slot_passOnVirtualViewPlayMove(const int x, const int y){
    emit this->signal_playMove(x, y);
}

void GUI::slot_toggleScannerDebugImage()
{
    if (ui_main.scannerdebugimage_action->isChecked())
        emit signal_setScannerDebugImage(true);
    else
        emit signal_setScannerDebugImage(false);
}

//////////
//Public Slots
//////////

void GUI::slot_newImage(QImage image) {
        printf(">>> New Image arrived! '%d x %d' -- Format: %d <<<\n", image.width(), image.height(), image.format());
        augmented_view->setImage(image);
        augmented_view->rescaleImage(augmented_view->parentWidget()->size());
    }

void GUI::slot_newGameData(const GoBackend::Game* game) {
    // update internal pointer if the board has been changed
    if (go_game != game)
        go_game = game;

    auto& board = go_game->getBoard();

    auto current_player = board.ToPlay();

    // Updating basket pictures
    switch (current_player) {
    case SG_WHITE:
        ui_main.white_basket->setPixmap(whitebasket_pixmap);
        ui_main.black_basket->setPixmap(closedbasket_pixmap);
        break;
    case SG_BLACK:
        ui_main.white_basket->setPixmap(closedbasket_pixmap);
        ui_main.black_basket->setPixmap(blackbasket_pixmap);
        break;
    default:
        assert(false);
        break;
    }

    // Updating Game-Settings
    ui_main.movenumber_label->setText(QString::number(board.MoveNumber()));
    ui_main.kominumber_label->setText(QString::number(board.Rules().Komi().ToFloat()));
    ui_main.handicapnumber_label->setText(QString::number(board.Rules().Handicap()));
    ui_main.capturedwhite_label->setText(QString::number(board.NumPrisoners(SG_WHITE)));
    ui_main.capturedblack_label->setText(QString::number(board.NumPrisoners(SG_BLACK)));

    // refresh virtual view
    if (ui_main.big_container->toolTip() == "virtual view")
        virtual_view->createAndSetScene(ui_main.big_container->size(), &board);

    else if (ui_main.big_container->toolTip() == "augmented view")
        virtual_view->createAndSetScene(ui_main.small_container->size(), &board);

    printf(">>> New Game data! <<<\n");
}

void GUI::slot_showFinishedGameResults(QString result){
    QMessageBox::information(this, "Game results", result);
    auto answer = QMessageBox::question(this, "New Game?", "Do you want to start a new game?");
    if (answer == QMessageBox::Yes)
        this->slot_ButtonNewGame();
}

void GUI::slot_setupNewGame(QString game_name, QString blackplayer_name, QString whiteplayer_name, float komi){

    // emit to backend that gui wants to set up a new game!
    auto rules = GoRules(0, GoKomi(komi), true, true);
    emit signal_newGame(rules);

    // Setting up new names for players
    ui_main.gamename_label->setText(game_name);
    ui_main.blackplayer_label->setText(blackplayer_name);
    ui_main.whiteplayer_label->setText(whiteplayer_name);
    ui_main.kominumber_label->setText(QString::number(komi));
    ui_main.handicapnumber_label->setText(QString::number(0));
}

///////////
//Events
///////////

void GUI::closeEvent(QCloseEvent *event){

    // If at least one move was was done
    // TODO If game loaded -> move number greater than start number!
    int answer = 0;

    // if at least one move was made -> ask if user wants to save
    bool saveable = ui_main.movenumber_label->text().toInt() > 0;

    if (saveable)
        answer = QMessageBox::question(this, "Save?", "Do you want to save before quitting?", "Save", "Don't Save", "Cancel");
    else
        answer = QMessageBox::question(this, "Quit?", "Do you really want to quit?", "Quit", "Cancel");

    if(answer == 0 && saveable){
        this->slot_MenuSave();
        emit stop_backend_thread();
        event->accept();
    }
    else if((answer == 1 && saveable)
        || (answer == 0 && !saveable)){
        emit stop_backend_thread();
        event->accept();
    }
    else
        event->ignore();
}

} // namespace Go_GUI<|endoftext|>


<commit_before>#ifndef SRC_NODES_GENERIC_HPP_
#define SRC_NODES_GENERIC_HPP_

#include <core/traits.hpp>
#include <ports/ports.hpp>

#include <utility>
#include <map>

namespace fc
{

/**
 * \brief generic unary node which applys transform with parameter to all inputs
 *
 * \tparam bin_op binary operator, argument is input of node, second is parameter
 *
 * \pre bin_op needs to be callable with two argments
 */
template<class bin_op>
struct transform_node
{
	static_assert(utils::function_traits<bin_op>::arity == 2,
			"operator in transform node needs to take two parameters");
	typedef typename result_of<bin_op>::type result_type;
	typedef typename argtype_of<bin_op,1>::type param_type;
	typedef typename argtype_of<bin_op,0>::type data_t;

	explicit transform_node(bin_op op) : op(op) {}

	state_sink<param_type> param;

	decltype(auto) operator()(data_t&& in)
	{
		return op(in, param());
	}

private:
	bin_op op;
};

/// creates transform_node with op as operation.
template<class bin_op>
auto transform(bin_op op)
{
	return transform_node<bin_op>(op);
}

template<class data_t, class tag, class key_t = size_t> class n_ary_switch {};

template<class data_t, class key_t>
class n_ary_switch<data_t, state_tag, key_t>
{
public:
	typedef typename in_port<data_t, state_tag>::type port_t;

	n_ary_switch() :
		index() ,
		in_ports() ,
		out_port([this](){return  in_ports.at(index())();})
	{
	}

	auto in(key_t port) noexcept { return in_ports[port]; }
	/// parameter port controlling the switch, expects state of key_t
	auto control() const noexcept { return index; }
	auto out() const noexcept { return out_port; }
private:
	state_sink<key_t> index;
	std::map<key_t, port_t> in_ports;
	state_source_call_function<data_t> out_port;
};

template<class data_t, class key_t>
class n_ary_switch<data_t, event_tag, key_t>
{
public:
	typedef typename in_port<data_t, event_tag>::type port_t;

	/**
	 * \brief Get port by key. Creates port if none was found for key.
	 *
	 *
	 * \returns input port corresponding to key
	 * \param port, key by which port is identified.
	 * \post !in_ports.empty()
	 *
	 */
	auto in(key_t port)
	{
		if (in_ports.find(port) == end(in_ports))
		{
			in_ports.emplace(std::make_pair(
					port,
					port_t([this, port](const data_t& in)
							{ forward_call(in, port); }))
			);
		} //else the port already exists, we can just return it

		assert(!in_ports.empty());
		return in_ports.at(port);
	};

	/// output port of events of type data_t.
	auto out() const noexcept { return out_port; }
	/// parameter port controlling the switch, expects state of key_t
	auto control() const noexcept { return index; }

private:
	state_sink<size_t> index;
	event_out_port<data_t> out_port;
	std::map<key_t, port_t> in_ports;
	/// fires incoming event if and only if it is from the currently chosen port.
	void forward_call(data_t event, key_t port)
	{
		assert(!in_ports.empty());
		assert(in_ports.find(port) != end(in_ports));

		if (port == index())
			out().fire(event);
	}
};

}  // namespace fc

#endif /* SRC_NODES_GENERIC_HPP_ */
<commit_msg>slight change in reference of transform node<commit_after>#ifndef SRC_NODES_GENERIC_HPP_
#define SRC_NODES_GENERIC_HPP_

#include <core/traits.hpp>
#include <ports/ports.hpp>

#include <utility>
#include <map>

namespace fc
{

/**
 * \brief generic unary node which applys transform with parameter to all inputs
 *
 * \tparam bin_op binary operator, argument is input of node, second is parameter
 *
 * \pre bin_op needs to be callable with two argments
 */
template<class bin_op>
struct transform_node
{
	static_assert(utils::function_traits<bin_op>::arity == 2,
			"operator in transform node needs to take two parameters");
	typedef typename result_of<bin_op>::type result_type;
	typedef typename argtype_of<bin_op,1>::type param_type;
	typedef typename argtype_of<bin_op,0>::type data_t;

	explicit transform_node(bin_op op) : op(op) {}

	state_sink<param_type> param;

	decltype(auto) operator()(const data_t& in)
	{
		return op(in, param());
	}

private:
	bin_op op;
};

/// creates transform_node with op as operation.
template<class bin_op>
auto transform(bin_op op)
{
	return transform_node<bin_op>(op);
}

template<class data_t, class tag, class key_t = size_t> class n_ary_switch {};

template<class data_t, class key_t>
class n_ary_switch<data_t, state_tag, key_t>
{
public:
	typedef typename in_port<data_t, state_tag>::type port_t;

	n_ary_switch() :
		index() ,
		in_ports() ,
		out_port([this](){return  in_ports.at(index())();})
	{
	}

	auto in(key_t port) noexcept { return in_ports[port]; }
	/// parameter port controlling the switch, expects state of key_t
	auto control() const noexcept { return index; }
	auto out() const noexcept { return out_port; }
private:
	state_sink<key_t> index;
	std::map<key_t, port_t> in_ports;
	state_source_call_function<data_t> out_port;
};

template<class data_t, class key_t>
class n_ary_switch<data_t, event_tag, key_t>
{
public:
	typedef typename in_port<data_t, event_tag>::type port_t;

	/**
	 * \brief Get port by key. Creates port if none was found for key.
	 *
	 *
	 * \returns input port corresponding to key
	 * \param port, key by which port is identified.
	 * \post !in_ports.empty()
	 *
	 */
	auto in(key_t port)
	{
		if (in_ports.find(port) == end(in_ports))
		{
			in_ports.emplace(std::make_pair(
					port,
					port_t([this, port](const data_t& in)
							{ forward_call(in, port); }))
			);
		} //else the port already exists, we can just return it

		assert(!in_ports.empty());
		return in_ports.at(port);
	};

	/// output port of events of type data_t.
	auto out() const noexcept { return out_port; }
	/// parameter port controlling the switch, expects state of key_t
	auto control() const noexcept { return index; }

private:
	state_sink<size_t> index;
	event_out_port<data_t> out_port;
	std::map<key_t, port_t> in_ports;
	/// fires incoming event if and only if it is from the currently chosen port.
	void forward_call(data_t event, key_t port)
	{
		assert(!in_ports.empty());
		assert(in_ports.find(port) != end(in_ports));

		if (port == index())
			out().fire(event);
	}
};

}  // namespace fc

#endif /* SRC_NODES_GENERIC_HPP_ */
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File StdSegExp.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Routines within Standard Segment Expansions
//
///////////////////////////////////////////////////////////////////////////////

#include <StdRegions/StdSegExp.h>

namespace Nektar
{
    namespace StdRegions
    {

	StdSegExp::StdSegExp(const LibUtilities::BasisKey &Ba):
	    StdExpansion1D(Ba,Ba.GetNumModes())
	{
	}

	StdSegExp::StdSegExp(const StdSegExp &T):
	    StdExpansion1D(T)
	{
	}

	StdSegExp::~StdSegExp()
	{
	}

	//----------------------------
	// Integration Methods
	//----------------------------

	double StdSegExp::Integral(const double *inarray)
	{
	    double Int = 0.0;
	    const double *z,*w0;
	    int    nquad0 = m_base[0]->GetNumPoints();
	    BstShrDArray tmp = GetDoubleTmpSpace(nquad0);

	    ExpPointsProperties(0)->GetZW(z,w0);

	    // multiply by integration constants
	    Vmath::Vmul(nquad0,(double*)inarray,1,(double*)w0,1,&tmp[0],1);

	    Int = Vmath::Vsum(nquad0,&tmp[0],1);

	    return Int;
	}

	void StdSegExp::IProductWRTBase(const double *base,
					const double * inarray,
					double * outarray, int coll_check)
	{
	    int    nquad = m_base[0]->GetNumPoints();
	    const double *z,*w;
	    BstShrDArray tmp  = GetDoubleTmpSpace(nquad);

	    ExpPointsProperties(0)->GetZW(z,w);

	    Vmath::Vmul(nquad,(double*)inarray,1,(double*)w,1,&tmp[0],1);

	    if(coll_check&&m_base[0]->Collocation())
	    {
		Vmath::Vcopy(nquad,&tmp[0],1,outarray,1);
	    }
	    else
	    {
		Blas::Dgemv('T',nquad,m_base[0]->GetNumModes(),1.0,base,nquad,
			    &tmp[0],1,0.0,outarray,1);
	    }

	}

	void StdSegExp::IProductWRTBase(const double *inarray, double *outarray)
	{
	    IProductWRTBase(m_base[0]->GetBdata(),inarray,outarray,1);
	}

	void StdSegExp::FillMode(const int mode, double *outarray)
	{
	    int   nquad = m_base[0]->GetNumPoints();
	    const double * base  = m_base[0]->GetBdata();

	    ASSERTL2(modes <= m_ncoeffs ,
	     "calling argument mode is larger than total expansion order");

	    Vmath::Vcopy(nquad,(double *)base+mode*nquad,1, outarray,1);
  }

	DNekMatSharedPtr StdSegExp::GenMassMatrix()
	{
	    DNekMatSharedPtr Mat = StdExpansion::GenerateMassMatrix();

	    // For Fourier basis set the imaginary component of mean mode
	    // to have a unit diagonal component in mass matrix
	    if(m_base[0]->GetBasisType() == LibUtilities::eFourier)
	    {
		(*Mat)(1,1) = 1.0;
	    }

	    return Mat;
	}

	DNekMatSharedPtr StdSegExp::GenLapMatrix()
	{
	    int    i;
	    int   nquad = m_base[0]->GetNumPoints();
	    const double * dbase  = m_base[0]->GetDbdata();
	    const double *z,*w;
	    BstShrDArray tmp  = GetDoubleTmpSpace(nquad);
	    int nummodes = m_base[0]->GetNumModes();
	    DNekMatSharedPtr Mat;

	    //	    Mat.reset(new DNekMat(nummodes,nummodes,
	    // new double [nummodes*nummodes]));
	    Mat = MemoryManager::AllocateSharedPtr<DNekMat>(nummodes,nummodes,MemoryManager::AllocateArray<double>(nummodes*nummodes));

	    ExpPointsProperties(0)->GetZW(z,w);

	    for(i = 0; i < nummodes; ++i)
	    {
		Vmath::Vcopy(nquad,(double *)dbase+i*nquad,1, &tmp[0],1);
		IProductWRTBase(m_base[0]->GetDbdata(), &tmp[0],
				&((*Mat).GetPtr())[0]+
				i*m_base[0]->GetNumModes(),0);
	    }

	    return Mat;
	}

	//----------------------------
	// Differentiation Methods
	//-----------------------------

	inline void StdSegExp::PhysDeriv(double * outarray)
	{
	    PhysTensorDeriv(outarray);
	}

	void StdSegExp::PhysDeriv(const double *inarray, double * outarray)
	{
	    PhysTensorDeriv(inarray,outarray);
	}

	//----------------------------
	// Evaluation Methods
	//----------------------------

	void StdSegExp::BwdTrans(double * outarray)
	{
	    int           nquad = m_base[0]->GetNumPoints();
	    const double *base  = m_base[0]->GetBdata();

	    if(m_base[0]->Collocation())
	    {
		Vmath::Vcopy(nquad,&m_coeffs[0],1,outarray,1);
	    }
	    else
	    {
		Blas::Dgemv('N',nquad,m_base[0]->GetNumModes(),1.0,base,nquad,
			    &m_coeffs[0],1,0.0,outarray,1);
	    }
	}

	void StdSegExp::FwdTrans(const double *inarray)
	{
	    if(m_base[0]->Collocation())
	    {
		Vmath::Vcopy(GetNcoeffs(),inarray,1,&m_coeffs[0],1);
	    }
	    else{
		IProductWRTBase(inarray,&m_coeffs[0]);

		DNekVec v(m_ncoeffs,&m_coeffs[0]);
		DNekLinSys matsys(*GenMassMatrix(),v);

		BstShrDArray tmp = GetDoubleTmpSpace(m_ncoeffs);
		DNekVec sol(m_ncoeffs,&tmp[0]);
		sol = matsys.Solve();
		Blas::Dcopy(m_ncoeffs,&tmp[0],1,&m_coeffs[0],1);
	    }
	}

	double StdSegExp::Evaluate(const double *Lcoord)
	{
	    return PhysEvaluate(Lcoord);
	}

	void StdSegExp::MapTo(EdgeOrientation dir, StdExpMap& Map)
	{

	    if(Map.GetLen() < 2)
	    {
		Map.SetMapMemory(2);
	    }

	    switch(m_base[0]->GetBasisType())
	    {
	    case LibUtilities::eGLL_Lagrange:
		{
		    int order = m_base[0]->GetNumModes();
		    if(dir == eForwards)
		    {
			Map[0] = 0;
			Map[1] = order-1;
		    }
		    else
		    {
			Map[0] = order-1;
			Map[1] = 0;
		    }
		}
		break;
	    case LibUtilities::eModified_A:

		if(dir == eForwards)
		{
		    Map[0] = 0;
		    Map[1] = 1;
		}
		else
		{
		    Map[0] = 1;
		    Map[1] = 0;
		}
		break;
	    default:
		ASSERTL0(0,"Mapping not defined for this expansion");
	    }
	}

	void StdSegExp::GetCoords(double **coords)
	{
	    Blas::Dcopy(GetNumPoints(0),ExpPointsProperties(0)->GetZ(),
			1,coords[0],1);
	}

    }//end namespace
}//end namespace

/**
 * $Log: StdSegExp.cpp,v $
 * Revision 1.10  2007/01/28 18:34:24  sherwin
 * More modifications to make Demo Project1D compile
 *
 * Revision 1.9  2007/01/23 23:20:21  sherwin
 * New version after Jan 07 update
 *
 * Revision 1.8  2007/01/20 22:35:21  sherwin
 * Version with StdExpansion compiling
 *
 * Revision 1.7  2007/01/15 15:07:20  pvos
 * updating doxygen documentation
 *
 * Revision 1.6  2006/12/10 19:00:54  sherwin
 * Modifications to handle nodal expansions
 *
 * Revision 1.5  2006/08/16 23:34:42  jfrazier
 * *** empty log message ***
 *
 * Revision 1.4  2006/08/05 19:03:48  sherwin
 * Update to make the multiregions 2D expansion in connected regions work
 *
 * Revision 1.3  2006/06/06 15:25:21  jfrazier
 * Removed unreferenced variables and replaced ASSERTL0(false, ....) with
 * NEKERROR.
 *
 * Revision 1.2  2006/06/01 13:43:20  kirby
 * *** empty log message ***
 *
 * Revision 1.1  2006/05/04 18:58:33  kirby
 * *** empty log message ***
 *
 * Revision 1.52  2006/04/01 21:59:27  sherwin
 * Sorted new definition of ASSERT
 *
 * Revision 1.51  2006/03/21 09:21:32  sherwin
 * Introduced NekMemoryManager
 *
 * Revision 1.50  2006/03/05 22:11:03  sherwin
 *
 * Sorted out Project1D, Project2D and Project_Diff2D as well as some test scripts
 *
 * Revision 1.49  2006/03/01 08:25:04  sherwin
 *
 * First compiling version of StdRegions
 *
 * Revision 1.48  2006/02/26 23:37:30  sherwin
 *
 * Updates and compiling checks upto StdExpansions1D
 *
 **/

<commit_msg>Modifcations to make a working version of Project1D<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File StdSegExp.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Routines within Standard Segment Expansions
//
///////////////////////////////////////////////////////////////////////////////

#include <StdRegions/StdSegExp.h>

namespace Nektar
{
    namespace StdRegions
    {

	StdSegExp::StdSegExp(const LibUtilities::BasisKey &Ba):
	    StdExpansion1D(Ba,Ba.GetNumModes())
	{
	}

	StdSegExp::StdSegExp(const StdSegExp &T):
	    StdExpansion1D(T)
	{
	}

	StdSegExp::~StdSegExp()
	{
	}

	//----------------------------
	// Integration Methods
	//----------------------------

	double StdSegExp::Integral(const double *inarray)
	{
	    double Int = 0.0;
	    const double *z,*w0;
	    int    nquad0 = m_base[0]->GetNumPoints();
	    BstShrDArray tmp = GetDoubleTmpSpace(nquad0);

	    ExpPointsProperties(0)->GetZW(z,w0);

	    // multiply by integration constants
	    Vmath::Vmul(nquad0,(double*)inarray,1,(double*)w0,1,&tmp[0],1);

	    Int = Vmath::Vsum(nquad0,&tmp[0],1);

	    return Int;
	}

	void StdSegExp::IProductWRTBase(const double *base,
					const double * inarray,
					double * outarray, int coll_check)
	{
	    int    nquad = m_base[0]->GetNumPoints();
	    const double *z,*w;
	    BstShrDArray tmp  = GetDoubleTmpSpace(nquad);

	    ExpPointsProperties(0)->GetZW(z,w);

	    Vmath::Vmul(nquad,(double*)inarray,1,(double*)w,1,&tmp[0],1);

	    if(coll_check&&m_base[0]->Collocation())
	    {
		Vmath::Vcopy(nquad,&tmp[0],1,outarray,1);
	    }
	    else
	    {
		Blas::Dgemv('T',nquad,m_base[0]->GetNumModes(),1.0,base,nquad,
			    &tmp[0],1,0.0,outarray,1);
	    }

	}

	void StdSegExp::IProductWRTBase(const double *inarray, double *outarray)
	{
	    IProductWRTBase(m_base[0]->GetBdata(),inarray,outarray,1);
	}

	void StdSegExp::FillMode(const int mode, double *outarray)
	{
	    int   nquad = m_base[0]->GetNumPoints();
	    const double * base  = m_base[0]->GetBdata();

	    ASSERTL2(modes <= m_ncoeffs ,
	     "calling argument mode is larger than total expansion order");

	    Vmath::Vcopy(nquad,(double *)base+mode*nquad,1, outarray,1);
  }

	DNekMatSharedPtr StdSegExp::GenMassMatrix()
	{
	    DNekMatSharedPtr Mat = StdExpansion::GenerateMassMatrix();

	    // For Fourier basis set the imaginary component of mean mode
	    // to have a unit diagonal component in mass matrix
	    if(m_base[0]->GetBasisType() == LibUtilities::eFourier)
	    {
		(*Mat)(1,1) = 1.0;
	    }

	    return Mat;
	}

	DNekMatSharedPtr StdSegExp::GenLapMatrix()
	{
	    int    i;
	    int   nquad = m_base[0]->GetNumPoints();
	    const double * dbase  = m_base[0]->GetDbdata();
	    const double *z,*w;
	    BstShrDArray tmp  = GetDoubleTmpSpace(nquad);
	    int nummodes = m_base[0]->GetNumModes();
	    DNekMatSharedPtr Mat;

	    //	    Mat.reset(new DNekMat(nummodes,nummodes,
	    // new double [nummodes*nummodes]));
	    Mat = MemoryManager::AllocateSharedPtr<DNekMat>(nummodes,nummodes,MemoryManager::AllocateArray<double>(nummodes*nummodes));

	    ExpPointsProperties(0)->GetZW(z,w);

	    for(i = 0; i < nummodes; ++i)
	    {
		Vmath::Vcopy(nquad,(double *)dbase+i*nquad,1, &tmp[0],1);
		IProductWRTBase(m_base[0]->GetDbdata(), &tmp[0],
				&((*Mat).GetPtr())[0]+
				i*m_base[0]->GetNumModes(),0);
	    }

	    return Mat;
	}

	//----------------------------
	// Differentiation Methods
	//-----------------------------

	inline void StdSegExp::PhysDeriv(double * outarray)
	{
	    PhysTensorDeriv(outarray);
	}

	void StdSegExp::PhysDeriv(const double *inarray, double * outarray)
	{
	    PhysTensorDeriv(inarray,outarray);
	}

	//----------------------------
	// Evaluation Methods
	//----------------------------

	void StdSegExp::BwdTrans(double * outarray)
	{
	    int           nquad = m_base[0]->GetNumPoints();
	    const double *base  = m_base[0]->GetBdata();

	    if(m_base[0]->Collocation())
	    {
		Vmath::Vcopy(nquad,&m_coeffs[0],1,outarray,1);
	    }
	    else
	    {
		Blas::Dgemv('N',nquad,m_base[0]->GetNumModes(),1.0,base,nquad,
			    &m_coeffs[0],1,0.0,outarray,1);
	    }
	}

	void StdSegExp::FwdTrans(const double *inarray)
	{
	    if(m_base[0]->Collocation())
	    {
		Vmath::Vcopy(GetNcoeffs(),inarray,1,&m_coeffs[0],1);
	    }
	    else{
		IProductWRTBase(inarray,&m_coeffs[0]);

		DNekVec          v(m_ncoeffs,&m_coeffs[0]);
#if 1
		DNekMatSharedPtr mass = GenMassMatrix();
		DNekLinSys       matsys(*mass,v);
#else

		DNekLinSys       matsys(*(GenMassMatrix()),v);
#endif

		BstShrDArray tmp = GetDoubleTmpSpace(m_ncoeffs);
		DNekVec sol(m_ncoeffs,&tmp[0]);
		sol = matsys.Solve();
		Blas::Dcopy(m_ncoeffs,&sol[0],1,&m_coeffs[0],1);
	    }
	}

	double StdSegExp::Evaluate(const double *Lcoord)
	{
	    return PhysEvaluate(Lcoord);
	}

	void StdSegExp::MapTo(EdgeOrientation dir, StdExpMap& Map)
	{

	    if(Map.GetLen() < 2)
	    {
		Map.SetMapMemory(2);
	    }

	    switch(m_base[0]->GetBasisType())
	    {
	    case LibUtilities::eGLL_Lagrange:
		{
		    int order = m_base[0]->GetNumModes();
		    if(dir == eForwards)
		    {
			Map[0] = 0;
			Map[1] = order-1;
		    }
		    else
		    {
			Map[0] = order-1;
			Map[1] = 0;
		    }
		}
		break;
	    case LibUtilities::eModified_A:

		if(dir == eForwards)
		{
		    Map[0] = 0;
		    Map[1] = 1;
		}
		else
		{
		    Map[0] = 1;
		    Map[1] = 0;
		}
		break;
	    default:
		ASSERTL0(0,"Mapping not defined for this expansion");
	    }
	}

	void StdSegExp::GetCoords(double **coords)
	{
	    Blas::Dcopy(GetNumPoints(0),ExpPointsProperties(0)->GetZ(),
			1,coords[0],1);
	}

    }//end namespace
}//end namespace

/**
 * $Log: StdSegExp.cpp,v $
 * Revision 1.11  2007/02/07 12:51:53  sherwin
 * Compiling version of Project1D
 *
 * Revision 1.10  2007/01/28 18:34:24  sherwin
 * More modifications to make Demo Project1D compile
 *
 * Revision 1.9  2007/01/23 23:20:21  sherwin
 * New version after Jan 07 update
 *
 * Revision 1.8  2007/01/20 22:35:21  sherwin
 * Version with StdExpansion compiling
 *
 * Revision 1.7  2007/01/15 15:07:20  pvos
 * updating doxygen documentation
 *
 * Revision 1.6  2006/12/10 19:00:54  sherwin
 * Modifications to handle nodal expansions
 *
 * Revision 1.5  2006/08/16 23:34:42  jfrazier
 * *** empty log message ***
 *
 * Revision 1.4  2006/08/05 19:03:48  sherwin
 * Update to make the multiregions 2D expansion in connected regions work
 *
 * Revision 1.3  2006/06/06 15:25:21  jfrazier
 * Removed unreferenced variables and replaced ASSERTL0(false, ....) with
 * NEKERROR.
 *
 * Revision 1.2  2006/06/01 13:43:20  kirby
 * *** empty log message ***
 *
 * Revision 1.1  2006/05/04 18:58:33  kirby
 * *** empty log message ***
 *
 * Revision 1.52  2006/04/01 21:59:27  sherwin
 * Sorted new definition of ASSERT
 *
 * Revision 1.51  2006/03/21 09:21:32  sherwin
 * Introduced NekMemoryManager
 *
 * Revision 1.50  2006/03/05 22:11:03  sherwin
 *
 * Sorted out Project1D, Project2D and Project_Diff2D as well as some test scripts
 *
 * Revision 1.49  2006/03/01 08:25:04  sherwin
 *
 * First compiling version of StdRegions
 *
 * Revision 1.48  2006/02/26 23:37:30  sherwin
 *
 * Updates and compiling checks upto StdExpansions1D
 *
 **/

<|endoftext|>


<commit_before>#include <AssertMacros.h>
#include <sys/conf.h>

#include <IOKit/scsi/SCSICommandOperationCodes.h>

#include "IOSCSITape.h"

#define super IOSCSIPrimaryCommandsDevice
OSDefineMetaClassAndStructors(IOSCSITape, IOSCSIPrimaryCommandsDevice)

/* The one really global operation of this kext is to register for a
 * character device major number. The constructors and destructors
 * get called on kext load/unload making it a great candidate for
 * IOKit-instance-spaning devices. */
class CdevMajorIniter
{
private:
	static unsigned int major;
	static struct cdevsw cdevsw;
public:
	CdevMajorIniter(void);
	~CdevMajorIniter(void);
};

CdevMajorIniter::CdevMajorIniter(void)
{
	major = cdevsw_add(-1, &cdevsw);
}

CdevMajorIniter::~CdevMajorIniter(void)
{
	major = cdevsw_remove(major, &cdevsw);
}

static CdevMajorIniter CdevMajorIniter;

int gTapeCounter = -1;

UInt32
IOSCSITape::GetInitialPowerState(void)
{
	return 0;
}

void
IOSCSITape::HandlePowerChange(void)
{
}

void
IOSCSITape::HandleCheckPowerState(void)
{
}

void
IOSCSITape::TicklePowerManager(void)
{
}

bool
IOSCSITape::InitializeDeviceSupport(void)
{
	/* For now, just increment the counter for each device. In the
	 * future we may want to implement some sort of reclamation of
	 * device types. */
	tapeNumber = ++gTapeCounter;

	/* always initialize */
	return true;
}

void
IOSCSITape::StartDeviceSupport(void)
{
}

void
IOSCSITape::SuspendDeviceSupport(void)
{
}

void
IOSCSITape::ResumeDeviceSupport(void)
{
}

void
IOSCSITape::StopDeviceSupport(void)
{
}

void
IOSCSITape::TerminateDeviceSupport(void)
{
}

UInt32
IOSCSITape::GetNumberOfPowerStateTransitions(void)
{
	return 0;
}

bool
IOSCSITape::ClearNotReadyStatus(void)
{
	return false;
}

#if 0
#pragma mark -
#pragma mark 0x01 SSC Implicit Address Commands
#pragma mark -
#endif /* 0 */

bool
IOSCSITape::ERASE_6(
	SCSITaskIdentifier	request,
	SCSICmdField1Bit	IMMED,
	SCSICmdField1Bit	LONG,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(IMMED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(LONG, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_ERASE,
							  (LONG << 1) |
							   IMMED,
							  0x00,
							  0x00,
							  0x00,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

ErrorExit:

	return result;
}

bool
IOSCSITape::READ_6(
	SCSITaskIdentifier		request,
	IOMemoryDescriptor *		readBuffer,
	UInt32					blockSize,
	SCSICmdField1Bit			SILI,
	SCSICmdField1Bit			FIXED,
	SCSICmdField3Byte		TRANSFER_LENGTH,
	SCSICmdField1Byte		CONTROL)
{
	UInt32	requestedByteCount	= 0;
	bool	result				= false;

	require(IsParameterValid(SILI, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(FIXED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(TRANSFER_LENGTH, kSCSICmdFieldMask3Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	if (FIXED)
		requestedByteCount = TRANSFER_LENGTH * blockSize;
	else
		requestedByteCount = TRANSFER_LENGTH;

	require((readBuffer != 0), ErrorExit);
	require((readBuffer->getLength() >= requestedByteCount), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_READ_6,
							  (SILI << 1) |
							   FIXED,
							  (TRANSFER_LENGTH >> 16) & 0xFF,
							  (TRANSFER_LENGTH >>  8) & 0xFF,
							   TRANSFER_LENGTH        & 0xFF,
							  CONTROL);

	SetDataBuffer(request, readBuffer);

	SetRequestedDataTransferCount(request, requestedByteCount);

	SetDataTransferDirection(request, kSCSIDataTransfer_FromTargetToInitiator);

	SetTimeoutDuration(request, kThirtySecondTimeoutInMS);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::SPACE_6(
	SCSITaskIdentifier	request,
	SCSICmdField4Bit	CODE,
	SCSICmdField3Byte	COUNT,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(CODE, kSCSICmdFieldMask4Bit), ErrorExit);

	/* allow a two's complement negative number in the 3-byte integer
	 * space to not cause an error with IsParameterValid() */
	if ((COUNT & 0xFF800000) == 0xFF800000)
		COUNT = COUNT & 0xFFFFFF;

	require(IsParameterValid(COUNT, kSCSICmdFieldMask3Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_SPACE,
							  CODE,
							  (COUNT >> 16) & 0xFF,
							  (COUNT >>  8) & 0xFF,
							   COUNT        & 0xFF,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::WRITE_6(
	SCSITaskIdentifier		request,
	IOMemoryDescriptor *	writeBuffer,
	UInt32					blockSize,
	SCSICmdField1Bit		FIXED,
	SCSICmdField3Byte		TRANSFER_LENGTH,
	SCSICmdField1Byte		CONTROL)
{
	UInt32	requestedByteCount	= 0;
	bool	result				= false;

	require(IsParameterValid(FIXED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(TRANSFER_LENGTH, kSCSICmdFieldMask3Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	if (FIXED)
		requestedByteCount = TRANSFER_LENGTH * blockSize;
	else
		requestedByteCount = TRANSFER_LENGTH;

	require((writeBuffer != 0), ErrorExit);
	require((writeBuffer->getLength() >= requestedByteCount), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_WRITE_6,
							  FIXED,
							  (TRANSFER_LENGTH >> 16) & 0xFF,
							  (TRANSFER_LENGTH >>  8) & 0xFF,
							   TRANSFER_LENGTH        & 0xFF,
							  CONTROL);

	SetDataBuffer(request, writeBuffer);

	SetRequestedDataTransferCount(request, requestedByteCount);

	SetDataTransferDirection(request, kSCSIDataTransfer_FromInitiatorToTarget);

	SetTimeoutDuration(request, kThirtySecondTimeoutInMS);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::WRITE_FILEMARKS_6(
	SCSITaskIdentifier	request,
	SCSICmdField1Bit	WSMK,
	SCSICmdField1Bit	IMMED,
	SCSICmdField3Byte	TRANSFER_LENGTH,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(WSMK, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(IMMED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(TRANSFER_LENGTH, kSCSICmdFieldMask3Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_WRITE_FILEMARKS,
							  (WSMK << 1) |
							   IMMED,
							  (TRANSFER_LENGTH >> 16) & 0xFF,
							  (TRANSFER_LENGTH >>  8) & 0xFF,
							   TRANSFER_LENGTH        & 0xFF,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

	result = true;

ErrorExit:

	return result;
}

#if 0
#pragma mark -
#pragma mark 0x01 SSC Common Commands
#pragma mark -
#endif /* 0 */

bool
IOSCSITape::LOAD_UNLOAD(
	SCSITaskIdentifier	request,
	SCSICmdField1Bit	IMMED,
	SCSICmdField1Bit	HOLD,
	SCSICmdField1Bit	EOT,
	SCSICmdField1Bit	RETEN,
	SCSICmdField1Bit	LOAD,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(IMMED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(HOLD, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(EOT, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(RETEN, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(LOAD, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_LOAD_UNLOAD,
							  IMMED,
							  0x00,
							  0x00,
							  (HOLD  << 3) |
							  (EOT   << 2) |
							  (RETEN << 1) |
							   LOAD,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::READ_BLOCK_LIMITS(
	SCSITaskIdentifier		request,
	IOMemoryDescriptor *	readBuffer,
	SCSICmdField1Byte		CONTROL)
{
	bool result = false;

	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	require((readBuffer != 0), ErrorExit);
	require((readBuffer->getLength() >= 6), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_READ_BLOCK_LIMITS,
							  0x00,
							  0x00,
							  0x00,
							  0x00,
							  CONTROL);

	SetDataBuffer(request, readBuffer);

	SetRequestedDataTransferCount(request, 6);

	SetDataTransferDirection(request, kSCSIDataTransfer_FromTargetToInitiator);

	SetTimeoutDuration(request, kThirtySecondTimeoutInMS);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::READ_POSITION(
	SCSITaskIdentifier		request,
	IOMemoryDescriptor *	buffer,
	SCSICmdField5Bit		SERVICE_ACTION,
	SCSICmdField2Byte		ALLOCATION_LENGTH,
	SCSICmdField1Byte		CONTROL)
{
	bool	result	= false;
	int		count	= 0;

	require(IsParameterValid(SERVICE_ACTION, kSCSICmdFieldMask5Bit), ErrorExit);
	require(IsParameterValid(ALLOCATION_LENGTH, kSCSICmdFieldMask2Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	require((buffer != 0), ErrorExit);

	switch (SERVICE_ACTION)
	{
		case kSCSIReadPositionServiceAction_ShortFormBlockID:
		case kSCSIReadPositionServiceAction_ShortFormVendorSpecific:
			count = 20;
			break;
		case kSCSIReadPositionServiceAction_LongForm:
			count = 32;
			break;
		case kSCSIReadPositionServiceAction_ExtendedForm:
			count = 28;
			break;
		default:
			/* unknown service action */
			count = buffer->getLength();
			break;
	}

	require((buffer->getLength() >= count), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_READ_POSITION,
							  SERVICE_ACTION,
							  0x00,
							  0x00,
							  0x00,
							  0x00,
							  0x00,
							  (ALLOCATION_LENGTH >> 8) & 0xFF,
							   ALLOCATION_LENGTH       & 0xFF,
							  CONTROL);

	SetDataBuffer(request, buffer);

	SetRequestedDataTransferCount(request, count);

	SetDataTransferDirection(request, kSCSIDataTransfer_FromTargetToInitiator);

	SetTimeoutDuration(request, kThirtySecondTimeoutInMS);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::REWIND(
	SCSITaskIdentifier	request,
	SCSICmdField1Bit	IMMED,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(IMMED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_REWIND,
							  IMMED,
							  0x00,
							  0x00,
							  0x00,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

	result = true;

ErrorExit:

	return result;
}
<commit_msg>Fixed indent.<commit_after>#include <AssertMacros.h>
#include <sys/conf.h>

#include <IOKit/scsi/SCSICommandOperationCodes.h>

#include "IOSCSITape.h"

#define super IOSCSIPrimaryCommandsDevice
OSDefineMetaClassAndStructors(IOSCSITape, IOSCSIPrimaryCommandsDevice)

/* The one really global operation of this kext is to register for a
 * character device major number. The constructors and destructors
 * get called on kext load/unload making it a great candidate for
 * IOKit-instance-spaning devices. */
class CdevMajorIniter
{
private:
	static unsigned int major;
	static struct cdevsw cdevsw;
public:
	CdevMajorIniter(void);
	~CdevMajorIniter(void);
};

CdevMajorIniter::CdevMajorIniter(void)
{
	major = cdevsw_add(-1, &cdevsw);
}

CdevMajorIniter::~CdevMajorIniter(void)
{
	major = cdevsw_remove(major, &cdevsw);
}

static CdevMajorIniter CdevMajorIniter;

int gTapeCounter = -1;

UInt32
IOSCSITape::GetInitialPowerState(void)
{
	return 0;
}

void
IOSCSITape::HandlePowerChange(void)
{
}

void
IOSCSITape::HandleCheckPowerState(void)
{
}

void
IOSCSITape::TicklePowerManager(void)
{
}

bool
IOSCSITape::InitializeDeviceSupport(void)
{
	/* For now, just increment the counter for each device. In the
	 * future we may want to implement some sort of reclamation of
	 * device types. */
	tapeNumber = ++gTapeCounter;

	/* always initialize */
	return true;
}

void
IOSCSITape::StartDeviceSupport(void)
{
}

void
IOSCSITape::SuspendDeviceSupport(void)
{
}

void
IOSCSITape::ResumeDeviceSupport(void)
{
}

void
IOSCSITape::StopDeviceSupport(void)
{
}

void
IOSCSITape::TerminateDeviceSupport(void)
{
}

UInt32
IOSCSITape::GetNumberOfPowerStateTransitions(void)
{
	return 0;
}

bool
IOSCSITape::ClearNotReadyStatus(void)
{
	return false;
}

#if 0
#pragma mark -
#pragma mark 0x01 SSC Implicit Address Commands
#pragma mark -
#endif /* 0 */

bool
IOSCSITape::ERASE_6(
	SCSITaskIdentifier	request,
	SCSICmdField1Bit	IMMED,
	SCSICmdField1Bit	LONG,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(IMMED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(LONG, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_ERASE,
							  (LONG << 1) |
							   IMMED,
							  0x00,
							  0x00,
							  0x00,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

ErrorExit:

	return result;
}

bool
IOSCSITape::READ_6(
	SCSITaskIdentifier		request,
	IOMemoryDescriptor *	readBuffer,
	UInt32					blockSize,
	SCSICmdField1Bit		SILI,
	SCSICmdField1Bit		FIXED,
	SCSICmdField3Byte		TRANSFER_LENGTH,
	SCSICmdField1Byte		CONTROL)
{
	UInt32	requestedByteCount	= 0;
	bool	result				= false;

	require(IsParameterValid(SILI, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(FIXED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(TRANSFER_LENGTH, kSCSICmdFieldMask3Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	if (FIXED)
		requestedByteCount = TRANSFER_LENGTH * blockSize;
	else
		requestedByteCount = TRANSFER_LENGTH;

	require((readBuffer != 0), ErrorExit);
	require((readBuffer->getLength() >= requestedByteCount), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_READ_6,
							  (SILI << 1) |
							   FIXED,
							  (TRANSFER_LENGTH >> 16) & 0xFF,
							  (TRANSFER_LENGTH >>  8) & 0xFF,
							   TRANSFER_LENGTH        & 0xFF,
							  CONTROL);

	SetDataBuffer(request, readBuffer);

	SetRequestedDataTransferCount(request, requestedByteCount);

	SetDataTransferDirection(request, kSCSIDataTransfer_FromTargetToInitiator);

	SetTimeoutDuration(request, kThirtySecondTimeoutInMS);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::SPACE_6(
	SCSITaskIdentifier	request,
	SCSICmdField4Bit	CODE,
	SCSICmdField3Byte	COUNT,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(CODE, kSCSICmdFieldMask4Bit), ErrorExit);

	/* allow a two's complement negative number in the 3-byte integer
	 * space to not cause an error with IsParameterValid() */
	if ((COUNT & 0xFF800000) == 0xFF800000)
		COUNT = COUNT & 0xFFFFFF;

	require(IsParameterValid(COUNT, kSCSICmdFieldMask3Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_SPACE,
							  CODE,
							  (COUNT >> 16) & 0xFF,
							  (COUNT >>  8) & 0xFF,
							   COUNT        & 0xFF,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::WRITE_6(
	SCSITaskIdentifier		request,
	IOMemoryDescriptor *	writeBuffer,
	UInt32					blockSize,
	SCSICmdField1Bit		FIXED,
	SCSICmdField3Byte		TRANSFER_LENGTH,
	SCSICmdField1Byte		CONTROL)
{
	UInt32	requestedByteCount	= 0;
	bool	result				= false;

	require(IsParameterValid(FIXED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(TRANSFER_LENGTH, kSCSICmdFieldMask3Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	if (FIXED)
		requestedByteCount = TRANSFER_LENGTH * blockSize;
	else
		requestedByteCount = TRANSFER_LENGTH;

	require((writeBuffer != 0), ErrorExit);
	require((writeBuffer->getLength() >= requestedByteCount), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_WRITE_6,
							  FIXED,
							  (TRANSFER_LENGTH >> 16) & 0xFF,
							  (TRANSFER_LENGTH >>  8) & 0xFF,
							   TRANSFER_LENGTH        & 0xFF,
							  CONTROL);

	SetDataBuffer(request, writeBuffer);

	SetRequestedDataTransferCount(request, requestedByteCount);

	SetDataTransferDirection(request, kSCSIDataTransfer_FromInitiatorToTarget);

	SetTimeoutDuration(request, kThirtySecondTimeoutInMS);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::WRITE_FILEMARKS_6(
	SCSITaskIdentifier	request,
	SCSICmdField1Bit	WSMK,
	SCSICmdField1Bit	IMMED,
	SCSICmdField3Byte	TRANSFER_LENGTH,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(WSMK, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(IMMED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(TRANSFER_LENGTH, kSCSICmdFieldMask3Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_WRITE_FILEMARKS,
							  (WSMK << 1) |
							   IMMED,
							  (TRANSFER_LENGTH >> 16) & 0xFF,
							  (TRANSFER_LENGTH >>  8) & 0xFF,
							   TRANSFER_LENGTH        & 0xFF,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

	result = true;

ErrorExit:

	return result;
}

#if 0
#pragma mark -
#pragma mark 0x01 SSC Common Commands
#pragma mark -
#endif /* 0 */

bool
IOSCSITape::LOAD_UNLOAD(
	SCSITaskIdentifier	request,
	SCSICmdField1Bit	IMMED,
	SCSICmdField1Bit	HOLD,
	SCSICmdField1Bit	EOT,
	SCSICmdField1Bit	RETEN,
	SCSICmdField1Bit	LOAD,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(IMMED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(HOLD, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(EOT, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(RETEN, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(LOAD, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_LOAD_UNLOAD,
							  IMMED,
							  0x00,
							  0x00,
							  (HOLD  << 3) |
							  (EOT   << 2) |
							  (RETEN << 1) |
							   LOAD,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::READ_BLOCK_LIMITS(
	SCSITaskIdentifier		request,
	IOMemoryDescriptor *	readBuffer,
	SCSICmdField1Byte		CONTROL)
{
	bool result = false;

	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	require((readBuffer != 0), ErrorExit);
	require((readBuffer->getLength() >= 6), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_READ_BLOCK_LIMITS,
							  0x00,
							  0x00,
							  0x00,
							  0x00,
							  CONTROL);

	SetDataBuffer(request, readBuffer);

	SetRequestedDataTransferCount(request, 6);

	SetDataTransferDirection(request, kSCSIDataTransfer_FromTargetToInitiator);

	SetTimeoutDuration(request, kThirtySecondTimeoutInMS);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::READ_POSITION(
	SCSITaskIdentifier		request,
	IOMemoryDescriptor *	buffer,
	SCSICmdField5Bit		SERVICE_ACTION,
	SCSICmdField2Byte		ALLOCATION_LENGTH,
	SCSICmdField1Byte		CONTROL)
{
	bool	result	= false;
	int		count	= 0;

	require(IsParameterValid(SERVICE_ACTION, kSCSICmdFieldMask5Bit), ErrorExit);
	require(IsParameterValid(ALLOCATION_LENGTH, kSCSICmdFieldMask2Byte), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	require((buffer != 0), ErrorExit);

	switch (SERVICE_ACTION)
	{
		case kSCSIReadPositionServiceAction_ShortFormBlockID:
		case kSCSIReadPositionServiceAction_ShortFormVendorSpecific:
			count = 20;
			break;
		case kSCSIReadPositionServiceAction_LongForm:
			count = 32;
			break;
		case kSCSIReadPositionServiceAction_ExtendedForm:
			count = 28;
			break;
		default:
			/* unknown service action */
			count = buffer->getLength();
			break;
	}

	require((buffer->getLength() >= count), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_READ_POSITION,
							  SERVICE_ACTION,
							  0x00,
							  0x00,
							  0x00,
							  0x00,
							  0x00,
							  (ALLOCATION_LENGTH >> 8) & 0xFF,
							   ALLOCATION_LENGTH       & 0xFF,
							  CONTROL);

	SetDataBuffer(request, buffer);

	SetRequestedDataTransferCount(request, count);

	SetDataTransferDirection(request, kSCSIDataTransfer_FromTargetToInitiator);

	SetTimeoutDuration(request, kThirtySecondTimeoutInMS);

	result = true;

ErrorExit:

	return result;
}

bool
IOSCSITape::REWIND(
	SCSITaskIdentifier	request,
	SCSICmdField1Bit	IMMED,
	SCSICmdField1Byte	CONTROL)
{
	bool result = false;

	require(IsParameterValid(IMMED, kSCSICmdFieldMask1Bit), ErrorExit);
	require(IsParameterValid(CONTROL, kSCSICmdFieldMask1Byte), ErrorExit);

	SetCommandDescriptorBlock(request,
							  kSCSICmd_REWIND,
							  IMMED,
							  0x00,
							  0x00,
							  0x00,
							  CONTROL);

	SetDataTransferDirection(request, kSCSIDataTransfer_NoDataTransfer);

	result = true;

ErrorExit:

	return result;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <sstream>
#include <fstream>

#include "versioning.hpp"
#include "budget_exception.hpp"
#include "config.hpp"

namespace {

std::string exec_command(const std::string& command) {
    std::stringstream output;

    char buffer[1024];

    FILE* stream = popen(command.c_str(), "r");

    while (fgets(buffer, 1024, stream) != NULL) {
        output << buffer;
    }

    pclose(stream);

    return output.str();
}

} //end of anonymous namespace

void budget::versioning_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        std::cout << "Missing subcommand" << std::endl;
    } else {
        auto& subcommand = args[1];

        if(subcommand == "save"){
            std::cout << exec_command("git -C " + budget_folder() + " commit -a -m Update" ) << std::endl;
        } else if(subcommand == "sync"){
            std::cout << exec_command("git -C " + budget_folder() + " commit -a -m Update" ) << std::endl;
            std::cout << exec_command("git -C " + budget_folder() + " pull" ) << std::endl;
            std::cout << exec_command("git -C " + budget_folder() + " push" ) << std::endl;
        } else if(subcommand == "pull"){
            std::cout << exec_command("git -C " + budget_folder() + " pull" ) << std::endl;
        } else if(subcommand == "push"){
            std::cout << exec_command("git -C " + budget_folder() + " push" ) << std::endl;
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}
<commit_msg>Add status command to versioning<commit_after>//=======================================================================
// Copyright (c) 2013-2014 Baptiste Wicht.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <sstream>
#include <fstream>

#include "versioning.hpp"
#include "budget_exception.hpp"
#include "config.hpp"

namespace {

std::string exec_command(const std::string& command) {
    std::stringstream output;

    char buffer[1024];

    FILE* stream = popen(command.c_str(), "r");

    while (fgets(buffer, 1024, stream) != NULL) {
        output << buffer;
    }

    pclose(stream);

    return output.str();
}

} //end of anonymous namespace

void budget::versioning_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        std::cout << "Missing subcommand" << std::endl;
    } else {
        auto& subcommand = args[1];

        if(subcommand == "save"){
            std::cout << exec_command("git -C " + budget_folder() + " commit -a -m Update" ) << std::endl;
        } else if(subcommand == "sync"){
            std::cout << exec_command("git -C " + budget_folder() + " commit -a -m Update" ) << std::endl;
            std::cout << exec_command("git -C " + budget_folder() + " pull" ) << std::endl;
            std::cout << exec_command("git -C " + budget_folder() + " push" ) << std::endl;
        } else if(subcommand == "pull"){
            std::cout << exec_command("git -C " + budget_folder() + " pull" ) << std::endl;
        } else if(subcommand == "push"){
            std::cout << exec_command("git -C " + budget_folder() + " push" ) << std::endl;
        } else if(subcommand == "status"){
            std::cout << exec_command("git -C " + budget_folder() + " status" ) << std::endl;
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}
<|endoftext|>