<commit_before>/*************************************************************************
> File Name: Combat.cpp
> Project Name: Hearthstonepp
> Author: Young-Joong Kim
> Purpose: Implement CombatTask
> Created Time: 2018/07/21
> Copyright (c) 2018, Young-Joong Kim
*************************************************************************/
#include <Tasks/BasicTasks/CombatTask.h>
#include <Tasks/BasicTasks/ModifyHealthTask.h>
#include <Tasks/PowerTasks/PoisonousTask.h>
#include <Tasks/PowerTasks/FreezeTask.h>

namespace Hearthstonepp::BasicTasks
{
CombatTask::CombatTask(TaskAgent& agent)
    : m_requirement(TaskID::SELECT_TARGET, agent)
{
    // Do Nothing
}

TaskID CombatTask::GetTaskID() const
{
    return TaskID::COMBAT;
}

MetaData CombatTask::Impl(Player& player1, Player& player2)
{
    TaskMeta serialized;
    // Get Targeting Response from GameInterface
    m_requirement.Interact(player1.id, serialized);

    using RequireTaskMeta = FlatData::ResponseTarget;
    const auto& buffer = serialized.GetConstBuffer();
    auto req = flatbuffers::GetRoot<RequireTaskMeta>(buffer.get());

    if (req == nullptr)
    {
        return MetaData::COMBAT_FLATBUFFER_NULLPTR;
    }

    BYTE src = req->src();
    BYTE dst = req->dst();

    source = (src > 0) ? dynamic_cast<Character*>(player1.field[src - 1])
                       : dynamic_cast<Character*>(player1.hero);
    target = (dst > 0) ? dynamic_cast<Character*>(player2.field[dst - 1])
                       : dynamic_cast<Character*>(player2.hero);

    // Source Minion Index Verification
    if (src > player1.field.size())
    {
        return MetaData::COMBAT_SRC_IDX_OUT_OF_RANGE;
    }

    // Source Minion Verification for Attacked Vector
    if (source->attackableCount == 0)
    {
        return MetaData::COMBAT_ALREADY_ATTACKED;
    }

    source->attackableCount--;

    // Destination Verification
    // dst == 0 : hero
    // 1 < dst <= field.size : minion
    if (dst > player2.field.size())
    {
        return MetaData::COMBAT_DST_IDX_OUT_OF_RANGE;
    }

    // Taunt Verification
    if (target->gameTags[+GameTag::TAUNT] == 0)
    for (auto& item: player2.field)
    {
        if (item->gameTags[+GameTag::TAUNT] == 1)
        {
            return MetaData::COMBAT_FIELD_HAVE_TAUNT;
        }
    }

    // Stealth Verification
    if (target->gameTags[+GameTag::STEALTH] == 1)
    {
        return MetaData::COMBAT_TARGET_STEALTH;
    }

    BYTE sourceAttack = static_cast<BYTE>(source->attack);
    BYTE targetAttack = (dst > 0) ? static_cast<BYTE>(target->attack) : 0;

    // Attack : Dst -> Src
    MetaData hurtedSrc =
        ModifyHealthTask(source, targetAttack).Run(player1, player2);
    if (hurtedSrc != MetaData::MODIFY_HEALTH_SUCCESS)
    {
        return hurtedSrc;
    }

    // Attack : Src -> Dst
    MetaData hurtedDst =
        ModifyHealthTask(target, sourceAttack).Run(player1, player2);
    if (hurtedDst != MetaData::MODIFY_HEALTH_SUCCESS)
    {
        return hurtedDst;
    }

    // Divine Shield : Dst
    if (target->gameTags[+GameTag::DIVINE_SHIELD] == 1)
    {
        target->gameTags[+GameTag::DIVINE_SHIELD] = 0;
    }
    else
    {
        // Poisonous : Src -> Dst
        if (source->gameTags[+GameTag::POISONOUS] == 1)
        {
            PowerTask::PoisonousTask(source, target).Run(player1, player2);
        }
    }

    // Divine Shield : Src
    if (source->gameTags[+GameTag::DIVINE_SHIELD] == 1)
    {
        source->gameTags[+GameTag::DIVINE_SHIELD] = 0;
    }
    else
    {
        // Poisonous : Dst -> Src
        if (target->gameTags[+GameTag::POISONOUS] == 1)
        {
            PowerTask::PoisonousTask(target, source).Run(player1, player2);
        }
    }

    // Source Health Check
    if (source->health == 0)
    {
        auto& field = player1.field;
        auto ptr = std::find(field.begin(), field.end(), source);
        if (ptr != field.end())
        {
            *ptr = nullptr;
            field.erase(ptr);
        }
    }

    // Target Health Check
    if (target->health == 0)
    {
        auto& field = player2.field;
        auto ptr = std::find(field.begin(), field.end(), target);
        if (ptr != field.end())
        {
            *ptr = nullptr;
            field.erase(ptr);
        }
    }

    return MetaData::COMBAT_SUCCESS;
}
}  // namespace Hearthstonepp::BasicTasks<commit_msg>[ci skip] Fix CombatTask - moved check attackable count<commit_after>/*************************************************************************
> File Name: Combat.cpp
> Project Name: Hearthstonepp
> Author: Young-Joong Kim
> Purpose: Implement CombatTask
> Created Time: 2018/07/21
> Copyright (c) 2018, Young-Joong Kim
*************************************************************************/
#include <Tasks/BasicTasks/CombatTask.h>
#include <Tasks/BasicTasks/ModifyHealthTask.h>
#include <Tasks/PowerTasks/PoisonousTask.h>
#include <Tasks/PowerTasks/FreezeTask.h>

namespace Hearthstonepp::BasicTasks
{
CombatTask::CombatTask(TaskAgent& agent)
    : m_requirement(TaskID::SELECT_TARGET, agent)
{
    // Do Nothing
}

TaskID CombatTask::GetTaskID() const
{
    return TaskID::COMBAT;
}

MetaData CombatTask::Impl(Player& player1, Player& player2)
{
    TaskMeta serialized;
    // Get Targeting Response from GameInterface
    m_requirement.Interact(player1.id, serialized);

    using RequireTaskMeta = FlatData::ResponseTarget;
    const auto& buffer = serialized.GetConstBuffer();
    auto req = flatbuffers::GetRoot<RequireTaskMeta>(buffer.get());

    if (req == nullptr)
    {
        return MetaData::COMBAT_FLATBUFFER_NULLPTR;
    }

    BYTE src = req->src();
    BYTE dst = req->dst();

    source = (src > 0) ? dynamic_cast<Character*>(player1.field[src - 1])
                       : dynamic_cast<Character*>(player1.hero);
    target = (dst > 0) ? dynamic_cast<Character*>(player2.field[dst - 1])
                       : dynamic_cast<Character*>(player2.hero);

    // Source Minion Index Verification
    if (src > player1.field.size())
    {
        return MetaData::COMBAT_SRC_IDX_OUT_OF_RANGE;
    }

    // Destination Verification
    // dst == 0 : hero
    // 1 < dst <= field.size : minion
    if (dst > player2.field.size())
    {
        return MetaData::COMBAT_DST_IDX_OUT_OF_RANGE;
    }

    // Taunt Verification
    if (target->gameTags[+GameTag::TAUNT] == 0)
    for (auto& item: player2.field)
    {
        if (item->gameTags[+GameTag::TAUNT] == 1)
        {
            return MetaData::COMBAT_FIELD_HAVE_TAUNT;
        }
    }

    // Stealth Verification
    if (target->gameTags[+GameTag::STEALTH] == 1)
    {
        return MetaData::COMBAT_TARGET_STEALTH;
    }

    // Source Minion Verification for Attacked Vector
    if (source->attackableCount == 0)
    {
        return MetaData::COMBAT_ALREADY_ATTACKED;
    }

    source->attackableCount--;

    BYTE sourceAttack = static_cast<BYTE>(source->attack);
    BYTE targetAttack = (dst > 0) ? static_cast<BYTE>(target->attack) : 0;

    // Attack : Dst -> Src
    MetaData hurtedSrc =
        ModifyHealthTask(source, targetAttack).Run(player1, player2);
    if (hurtedSrc != MetaData::MODIFY_HEALTH_SUCCESS)
    {
        return hurtedSrc;
    }

    // Attack : Src -> Dst
    MetaData hurtedDst =
        ModifyHealthTask(target, sourceAttack).Run(player1, player2);
    if (hurtedDst != MetaData::MODIFY_HEALTH_SUCCESS)
    {
        return hurtedDst;
    }

    // Divine Shield : Dst
    if (target->gameTags[+GameTag::DIVINE_SHIELD] == 1)
    {
        target->gameTags[+GameTag::DIVINE_SHIELD] = 0;
    }
    else
    {
        // Poisonous : Src -> Dst
        if (source->gameTags[+GameTag::POISONOUS] == 1)
        {
            PowerTask::PoisonousTask(source, target).Run(player1, player2);
        }
    }

    // Divine Shield : Src
    if (source->gameTags[+GameTag::DIVINE_SHIELD] == 1)
    {
        source->gameTags[+GameTag::DIVINE_SHIELD] = 0;
    }
    else
    {
        // Poisonous : Dst -> Src
        if (target->gameTags[+GameTag::POISONOUS] == 1)
        {
            PowerTask::PoisonousTask(target, source).Run(player1, player2);
        }
    }

    // Source Health Check
    if (source->health == 0)
    {
        auto& field = player1.field;
        auto ptr = std::find(field.begin(), field.end(), source);
        if (ptr != field.end())
        {
            *ptr = nullptr;
            field.erase(ptr);
        }
    }

    // Target Health Check
    if (target->health == 0)
    {
        auto& field = player2.field;
        auto ptr = std::find(field.begin(), field.end(), target);
        if (ptr != field.end())
        {
            *ptr = nullptr;
            field.erase(ptr);
        }
    }

    return MetaData::COMBAT_SUCCESS;
}
}  // namespace Hearthstonepp::BasicTasks<|endoftext|>


<commit_before>#include "util/mt19937ar.h"
#include "util/exceptions.h"

#include "ProcedureInterpreter.h"
#include "ComboProcedure.h"
#include "ComboSelectProcedure.h"
#include "RunningProcedureId.h"
#include "NetworkElement.h"

namespace Procedure {
    using namespace boost;

    void ProcedureInterpreter::run(MessagingSystem::NetworkElement *ne) {
        // For now, comboInterpreter is a separate IdleTask. Otherwise, the next line should be uncommented.
        //comboInterpreter->run(ne);
        Set toBeRemoved;
        // Runs each pending RunningBuildInProcedure and checks status of any procedure.
        for (Map::iterator it = _map.begin(); it != _map.end(); it++) {
            RunningBuiltInProcedure* rbp = get<RunningBuiltInProcedure>(&(it->second));
            if (rbp) {
                rbp->run();
                if (rbp->isFinished()) {
                    toBeRemoved.insert(it->first);
                    if (rbp->isFailed()) {
                        _failed.insert(it->first);
                    } else {
                        _resultMap[it->first] = rbp->getResult();
                    }
                }
            } else {
                RunningProcedureId rcpID = get<RunningProcedureId>(it->second);
                if (comboInterpreter->isFinished(rcpID)) {
                    toBeRemoved.insert(it->first);
                    if (comboInterpreter->isFailed(rcpID)) {
                        _failed.insert(it->first);
                    } else {
                        _resultMap[it->first] = comboInterpreter->getResult(rcpID);
                        _unifierResultMap[it->first] = comboInterpreter->getUnifierResult(rcpID);
                    }
                }
            }

        }
        for (Set::iterator it = toBeRemoved.begin(); it != toBeRemoved.end(); it++) {
            _map.erase(*it);
        }
    }

    ProcedureInterpreter::ProcedureInterpreter(PerceptionActionInterface::PAI& p) : _pai(&p) {
        //initialize the random generator
        unsigned long rand_seed;
        if (MessagingSystem::NetworkElement::parameters.get("AUTOMATED_SYSTEM_TESTS") == "1") {
            rand_seed = 0;
        } else {
            rand_seed = time(NULL);
        }
        rng = new opencog::MT19937RandGen(rand_seed);
        logger().log(opencog::Logger::INFO, "Created random number generator (%p) for ComboInterpreter with seed %lu", rng, rand_seed);
        comboInterpreter = new ComboInterpreter(*_pai,*rng);
        comboSelectInterpreter = new ComboSelectInterpreter(*_pai, *rng);
        _next = 0;
    }

    ProcedureInterpreter::~ProcedureInterpreter() {
        delete comboInterpreter;
        delete comboSelectInterpreter;
        delete rng;
    }

    RunningProcedureID ProcedureInterpreter::runProcedure(const GeneralProcedure& p, const std::vector<combo::vertex>& arguments) {

        logger().log(opencog::Logger::INFO,
                        "ProcedureInterpreter - runProcedure(%s)", p.getName().c_str());

        if (p.getType() == COMBO) {
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a combo procedure.");
            RunningProcedureId rcpID = comboInterpreter->runProcedure(((const ComboProcedure&) p).getComboTree(), arguments);
            _map.insert(make_pair(++_next,rcpID));
        } else if(p.getType() == COMBO_SELECT){
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a combo select procedure.");
            const ComboSelectProcedure& procedure = ((const ComboSelectProcedure&) p);
            RunningProcedureId rcpID =
                comboSelectInterpreter->runProcedure(procedure.getFirstScript(),
                                                     procedure.getSecondScript(),
                                                     arguments);
            _map.insert(make_pair(++_next,rcpID));

        } else if (p.getType() == BUILT_IN) {
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a builtin procedure.");
            RunningBuiltInProcedure rbp = RunningBuiltInProcedure(*_pai, (const BuiltInProcedure&) p, arguments);
            // For now, runs built-in procedure immediately, since they are atomic
            // and caller may want to check for failure or get its result synchronously.
            rbp.run();
            _map.insert(make_pair(++_next,rbp));
        } else {
            opencog::cassert(TRACE_INFO, false, "ProcedureInterpreter -  unknown procedure type");
        }
        return _next;
    }

    RunningProcedureID ProcedureInterpreter::runProcedure(const GeneralProcedure& p, const std::vector<combo::vertex>& arguments, combo::variable_unifier& vu) {
        logger().log(opencog::Logger::INFO,
                        "ProcedureInterpreter - runProcedure(%s)", p.getName().c_str());

        if (p.getType() == COMBO) {
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a combo procedure.");
            RunningProcedureId rcpID = comboInterpreter->runProcedure(((const ComboProcedure&) p).getComboTree(), arguments, vu);
            _map.insert(make_pair(++_next,rcpID));

        } else if(p.getType() == COMBO_SELECT){
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a combo select procedure.");
            const ComboSelectProcedure& procedure = ((const ComboSelectProcedure&) p);
            RunningProcedureId rcpID = comboSelectInterpreter->runProcedure(procedure.getFirstScript(),
                                                                            procedure.getSecondScript(),
                                                                            arguments, vu);
            _map.insert(make_pair(++_next,rcpID));

        } else {
        	opencog::cassert(TRACE_INFO, false, "ProcedureInterpreter - Only combo procedures accept variable unifier parameters.");
        }
        return _next;
    }

    bool ProcedureInterpreter::isFinished(RunningProcedureID id) const {
        logger().log(opencog::Logger::FINE, "ProcedureInterpreter - isFinished(%lu).", id);
        bool result = true;
        Map::const_iterator it=_map.find(id);
        if (it != _map.end()) {
            RunningProcedure rp = it->second;
            RunningProcedureId* rpId;
            RunningBuiltInProcedure* rbp;
            if ((rbp = boost::get<RunningBuiltInProcedure>(&rp))) {
                result = rbp->isFinished();
            } else if((rpId = boost::get<RunningProcedureId>(&rp))) {
                if(rpId->getType() == COMBO){
                    result = comboInterpreter->isFinished(*rpId);
                } else if(rpId->getType() == COMBO_SELECT){
                    result = comboSelectInterpreter->isFinished(*rpId);
                }
            }
        }
        logger().log(opencog::Logger::DEBUG, "ProcedureInterpreter - isFinished(%lu)? Result: %d.",
                        id, result);
	return result;
    }

    bool ProcedureInterpreter::isFailed(RunningProcedureID id) const {
        logger().log(opencog::Logger::FINE, "ProcedureInterpreter - isFailed(%lu).", id);
        bool result = false;
        Map::const_iterator it=_map.find(id);
        if (it != _map.end()) {
            const RunningProcedureId* rpId;

            if ((rpId = boost::get<RunningProcedureId>(&(it->second)))) {
                if(rpId->getType() == COMBO){
                    result = comboInterpreter->isFailed(*rpId);
                } else if(rpId->getType() == COMBO_SELECT){
                    result = comboSelectInterpreter->isFailed(*rpId);
                }

            } else {
                result = boost::get<RunningBuiltInProcedure>(it->second).isFailed();
            }
        } else {
            result = (_failed.find(id)!=_failed.end());
        }
        logger().log(opencog::Logger::DEBUG, "ProcedureInterpreter - isFailed(%lu)? Result: %d.",
                        id, result);
	return result;
    }

    combo::vertex ProcedureInterpreter::getResult(RunningProcedureID id) {
        logger().log(opencog::Logger::FINE, "ProcedureInterpreter - getResult(%lu).", id);
        opencog::cassert(TRACE_INFO, isFinished(id), "ProcedureInterpreter - Procedure '%d' not finished.", id);
        opencog::cassert(TRACE_INFO, !isFailed(id), "ProcedureInterpreter - Procedure '%d' failed.", id);

        combo::vertex result = combo::id::action_success;
        Map::const_iterator it=_map.find(id);

        if (it != _map.end()) {
            RunningBuiltInProcedure* rbp;
            RunningProcedureId* rpId;
            RunningProcedure rp = it->second;

            if ((rbp = boost::get<RunningBuiltInProcedure>(&rp))) {
                result = rbp->getResult();

            } else if((rpId = boost::get<RunningProcedureId>(&rp))){
                if(rpId->getType() == COMBO){
                    result = comboInterpreter->getResult(*rpId);
                } else if(rpId->getType() == COMBO_SELECT){
                    result = comboSelectInterpreter->getResult(*rpId);
                }
            }

        } else {
            ResultMap::iterator it = _resultMap.find(id);
            opencog::cassert(TRACE_INFO, it != _resultMap.end(),
                    "ProcedureInterpreter - Cannot find result for procedure '%d'.", id);
            result= it->second;
        }
        return result;
    }

    combo::variable_unifier& ProcedureInterpreter::getUnifierResult(RunningProcedureID id){
        opencog::cassert(TRACE_INFO, isFinished(id), "ProcedureInterpreter - Procedure '%d' not finished.", id);
        opencog::cassert(TRACE_INFO, !isFailed(id), "ProcedureInterpreter - Procedure '%d' failed.", id);
        UnifierResultMap::iterator it = _unifierResultMap.find(id);
        opencog::cassert(TRACE_INFO, it != _unifierResultMap.end(),
                "ProcedureInterpreter - Cannot find unifier result for procedure '%d'.", id);
        return it->second;
    }

    void ProcedureInterpreter::stopProcedure(RunningProcedureID id) {
        logger().log(opencog::Logger::FINE, "ProcedureInterpreter - stopProcedure(%lu).", id);
        Map::iterator it=_map.find(id);
        if (it != _map.end()) {
            RunningProcedureId* rpId = boost::get<RunningProcedureId>(&(it->second));
            if (rpId->getType() == COMBO) {
                comboInterpreter->stopProcedure(*rpId);
            } else if(rpId->getType() == COMBO_SELECT){
                comboSelectInterpreter->stopProcedure(*rpId);
            }
            _map.erase(it);
        }
        Set::iterator failed_it = _failed.find(id);
        if (failed_it != _failed.end()) {
            _failed.erase(failed_it);
        }
        ResultMap::iterator result_it = _resultMap.find(id);
        if (result_it != _resultMap.end()) {
            _resultMap.erase(result_it);
        }
    }

    ComboInterpreter& ProcedureInterpreter::getComboInterpreter() const {
        return *comboInterpreter;
    }

    ComboSelectInterpreter& ProcedureInterpreter::getComboSelectInterpreter() const {
        return *comboSelectInterpreter;
    }

} //~namespace Procedure

<commit_msg>uncommented call to comboInterpreter.run() in ProcedureInterpreter.run() method, since there is no separate Task/Agent for running comboInterpreter separetely anymore<commit_after>#include "util/mt19937ar.h"
#include "util/exceptions.h"

#include "ProcedureInterpreter.h"
#include "ComboProcedure.h"
#include "ComboSelectProcedure.h"
#include "RunningProcedureId.h"
#include "NetworkElement.h"

namespace Procedure {
    using namespace boost;

    void ProcedureInterpreter::run(MessagingSystem::NetworkElement *ne) {

        // If a separate Agent is used for comboInterpreter, just comment the
        // next line :
        comboInterpreter->run(ne);

        Set toBeRemoved;
        // Runs each pending RunningBuildInProcedure and checks status of any procedure.
        for (Map::iterator it = _map.begin(); it != _map.end(); it++) {
            RunningBuiltInProcedure* rbp = get<RunningBuiltInProcedure>(&(it->second));
            if (rbp) {
                rbp->run();
                if (rbp->isFinished()) {
                    toBeRemoved.insert(it->first);
                    if (rbp->isFailed()) {
                        _failed.insert(it->first);
                    } else {
                        _resultMap[it->first] = rbp->getResult();
                    }
                }
            } else {
                RunningProcedureId rcpID = get<RunningProcedureId>(it->second);
                if (comboInterpreter->isFinished(rcpID)) {
                    toBeRemoved.insert(it->first);
                    if (comboInterpreter->isFailed(rcpID)) {
                        _failed.insert(it->first);
                    } else {
                        _resultMap[it->first] = comboInterpreter->getResult(rcpID);
                        _unifierResultMap[it->first] = comboInterpreter->getUnifierResult(rcpID);
                    }
                }
            }

        }
        for (Set::iterator it = toBeRemoved.begin(); it != toBeRemoved.end(); it++) {
            _map.erase(*it);
        }
    }

    ProcedureInterpreter::ProcedureInterpreter(PerceptionActionInterface::PAI& p) : _pai(&p) {
        //initialize the random generator
        unsigned long rand_seed;
        if (MessagingSystem::NetworkElement::parameters.get("AUTOMATED_SYSTEM_TESTS") == "1") {
            rand_seed = 0;
        } else {
            rand_seed = time(NULL);
        }
        rng = new opencog::MT19937RandGen(rand_seed);
        logger().log(opencog::Logger::INFO, "Created random number generator (%p) for ComboInterpreter with seed %lu", rng, rand_seed);
        comboInterpreter = new ComboInterpreter(*_pai,*rng);
        comboSelectInterpreter = new ComboSelectInterpreter(*_pai, *rng);
        _next = 0;
    }

    ProcedureInterpreter::~ProcedureInterpreter() {
        delete comboInterpreter;
        delete comboSelectInterpreter;
        delete rng;
    }

    RunningProcedureID ProcedureInterpreter::runProcedure(const GeneralProcedure& p, const std::vector<combo::vertex>& arguments) {

        logger().log(opencog::Logger::INFO,
                        "ProcedureInterpreter - runProcedure(%s)", p.getName().c_str());

        if (p.getType() == COMBO) {
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a combo procedure.");
            RunningProcedureId rcpID = comboInterpreter->runProcedure(((const ComboProcedure&) p).getComboTree(), arguments);
            _map.insert(make_pair(++_next,rcpID));
        } else if(p.getType() == COMBO_SELECT){
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a combo select procedure.");
            const ComboSelectProcedure& procedure = ((const ComboSelectProcedure&) p);
            RunningProcedureId rcpID =
                comboSelectInterpreter->runProcedure(procedure.getFirstScript(),
                                                     procedure.getSecondScript(),
                                                     arguments);
            _map.insert(make_pair(++_next,rcpID));

        } else if (p.getType() == BUILT_IN) {
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a builtin procedure.");
            RunningBuiltInProcedure rbp = RunningBuiltInProcedure(*_pai, (const BuiltInProcedure&) p, arguments);
            // For now, runs built-in procedure immediately, since they are atomic
            // and caller may want to check for failure or get its result synchronously.
            rbp.run();
            _map.insert(make_pair(++_next,rbp));
        } else {
            opencog::cassert(TRACE_INFO, false, "ProcedureInterpreter -  unknown procedure type");
        }
        return _next;
    }

    RunningProcedureID ProcedureInterpreter::runProcedure(const GeneralProcedure& p, const std::vector<combo::vertex>& arguments, combo::variable_unifier& vu) {
        logger().log(opencog::Logger::INFO,
                        "ProcedureInterpreter - runProcedure(%s)", p.getName().c_str());

        if (p.getType() == COMBO) {
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a combo procedure.");
            RunningProcedureId rcpID = comboInterpreter->runProcedure(((const ComboProcedure&) p).getComboTree(), arguments, vu);
            _map.insert(make_pair(++_next,rcpID));

        } else if(p.getType() == COMBO_SELECT){
            logger().log(opencog::Logger::DEBUG,
                            "ProcedureInterpreter - Running a combo select procedure.");
            const ComboSelectProcedure& procedure = ((const ComboSelectProcedure&) p);
            RunningProcedureId rcpID = comboSelectInterpreter->runProcedure(procedure.getFirstScript(),
                                                                            procedure.getSecondScript(),
                                                                            arguments, vu);
            _map.insert(make_pair(++_next,rcpID));

        } else {
        	opencog::cassert(TRACE_INFO, false, "ProcedureInterpreter - Only combo procedures accept variable unifier parameters.");
        }
        return _next;
    }

    bool ProcedureInterpreter::isFinished(RunningProcedureID id) const {
        logger().log(opencog::Logger::FINE, "ProcedureInterpreter - isFinished(%lu).", id);
        bool result = true;
        Map::const_iterator it=_map.find(id);
        if (it != _map.end()) {
            RunningProcedure rp = it->second;
            RunningProcedureId* rpId;
            RunningBuiltInProcedure* rbp;
            if ((rbp = boost::get<RunningBuiltInProcedure>(&rp))) {
                result = rbp->isFinished();
            } else if((rpId = boost::get<RunningProcedureId>(&rp))) {
                if(rpId->getType() == COMBO){
                    result = comboInterpreter->isFinished(*rpId);
                } else if(rpId->getType() == COMBO_SELECT){
                    result = comboSelectInterpreter->isFinished(*rpId);
                }
            }
        }
        logger().log(opencog::Logger::DEBUG, "ProcedureInterpreter - isFinished(%lu)? Result: %d.",
                        id, result);
	return result;
    }

    bool ProcedureInterpreter::isFailed(RunningProcedureID id) const {
        logger().log(opencog::Logger::FINE, "ProcedureInterpreter - isFailed(%lu).", id);
        bool result = false;
        Map::const_iterator it=_map.find(id);
        if (it != _map.end()) {
            const RunningProcedureId* rpId;

            if ((rpId = boost::get<RunningProcedureId>(&(it->second)))) {
                if(rpId->getType() == COMBO){
                    result = comboInterpreter->isFailed(*rpId);
                } else if(rpId->getType() == COMBO_SELECT){
                    result = comboSelectInterpreter->isFailed(*rpId);
                }

            } else {
                result = boost::get<RunningBuiltInProcedure>(it->second).isFailed();
            }
        } else {
            result = (_failed.find(id)!=_failed.end());
        }
        logger().log(opencog::Logger::DEBUG, "ProcedureInterpreter - isFailed(%lu)? Result: %d.",
                        id, result);
	return result;
    }

    combo::vertex ProcedureInterpreter::getResult(RunningProcedureID id) {
        logger().log(opencog::Logger::FINE, "ProcedureInterpreter - getResult(%lu).", id);
        opencog::cassert(TRACE_INFO, isFinished(id), "ProcedureInterpreter - Procedure '%d' not finished.", id);
        opencog::cassert(TRACE_INFO, !isFailed(id), "ProcedureInterpreter - Procedure '%d' failed.", id);

        combo::vertex result = combo::id::action_success;
        Map::const_iterator it=_map.find(id);

        if (it != _map.end()) {
            RunningBuiltInProcedure* rbp;
            RunningProcedureId* rpId;
            RunningProcedure rp = it->second;

            if ((rbp = boost::get<RunningBuiltInProcedure>(&rp))) {
                result = rbp->getResult();

            } else if((rpId = boost::get<RunningProcedureId>(&rp))){
                if(rpId->getType() == COMBO){
                    result = comboInterpreter->getResult(*rpId);
                } else if(rpId->getType() == COMBO_SELECT){
                    result = comboSelectInterpreter->getResult(*rpId);
                }
            }

        } else {
            ResultMap::iterator it = _resultMap.find(id);
            opencog::cassert(TRACE_INFO, it != _resultMap.end(),
                    "ProcedureInterpreter - Cannot find result for procedure '%d'.", id);
            result= it->second;
        }
        return result;
    }

    combo::variable_unifier& ProcedureInterpreter::getUnifierResult(RunningProcedureID id){
        opencog::cassert(TRACE_INFO, isFinished(id), "ProcedureInterpreter - Procedure '%d' not finished.", id);
        opencog::cassert(TRACE_INFO, !isFailed(id), "ProcedureInterpreter - Procedure '%d' failed.", id);
        UnifierResultMap::iterator it = _unifierResultMap.find(id);
        opencog::cassert(TRACE_INFO, it != _unifierResultMap.end(),
                "ProcedureInterpreter - Cannot find unifier result for procedure '%d'.", id);
        return it->second;
    }

    void ProcedureInterpreter::stopProcedure(RunningProcedureID id) {
        logger().log(opencog::Logger::FINE, "ProcedureInterpreter - stopProcedure(%lu).", id);
        Map::iterator it=_map.find(id);
        if (it != _map.end()) {
            RunningProcedureId* rpId = boost::get<RunningProcedureId>(&(it->second));
            if (rpId->getType() == COMBO) {
                comboInterpreter->stopProcedure(*rpId);
            } else if(rpId->getType() == COMBO_SELECT){
                comboSelectInterpreter->stopProcedure(*rpId);
            }
            _map.erase(it);
        }
        Set::iterator failed_it = _failed.find(id);
        if (failed_it != _failed.end()) {
            _failed.erase(failed_it);
        }
        ResultMap::iterator result_it = _resultMap.find(id);
        if (result_it != _resultMap.end()) {
            _resultMap.erase(result_it);
        }
    }

    ComboInterpreter& ProcedureInterpreter::getComboInterpreter() const {
        return *comboInterpreter;
    }

    ComboSelectInterpreter& ProcedureInterpreter::getComboSelectInterpreter() const {
        return *comboSelectInterpreter;
    }

} //~namespace Procedure

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cmdargs.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2005-10-27 17:27:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <osl/mutex.hxx>
#include <rtl/process.h>
#include <rtl/ustring.hxx>

rtl_uString ** g_ppCommandArgs = 0;
sal_uInt32     g_nCommandArgCount = 0;

struct rtl_CmdArgs_ArgHolder
{
    ~rtl_CmdArgs_ArgHolder();
};

rtl_CmdArgs_ArgHolder::~rtl_CmdArgs_ArgHolder()
{
    while (g_nCommandArgCount > 0)
        rtl_uString_release (g_ppCommandArgs[--g_nCommandArgCount]);

    rtl_freeMemory (g_ppCommandArgs);
    g_ppCommandArgs = 0;
}

static void impl_rtl_initCommandArgs()
{
    osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
    static rtl_CmdArgs_ArgHolder MyHolder;
    if (!g_ppCommandArgs)
    {
        sal_Int32 i, n = osl_getCommandArgCount();

        g_ppCommandArgs =
            (rtl_uString**)rtl_allocateZeroMemory (n * sizeof(rtl_uString*));
        for (i = 0; i < n; i++)
        {
            rtl_uString * pArg = 0;
            osl_getCommandArg (i, &pArg);
            if (('-' == pArg->buffer[0] || '/' == pArg->buffer[0]) &&
                 'e' == pArg->buffer[1] &&
                 'n' == pArg->buffer[2] &&
                 'v' == pArg->buffer[3] &&
                 ':' == pArg->buffer[4] &&
                rtl_ustr_indexOfChar (&(pArg->buffer[5]), '=') >= 0 )
            {
                // ignore.
                rtl_uString_release (pArg);
            }
            else
            {
                // assign.
                g_ppCommandArgs[g_nCommandArgCount++] = pArg;
            }
        }
    }
}

oslProcessError SAL_CALL rtl_getAppCommandArg (
    sal_uInt32 nArg, rtl_uString **ppCommandArg)
{
    if (!g_ppCommandArgs)
        impl_rtl_initCommandArgs();

    oslProcessError result = osl_Process_E_NotFound;
    if( nArg < g_nCommandArgCount )
    {
         rtl_uString_assign( ppCommandArg, g_ppCommandArgs[nArg] );
        result = osl_Process_E_None;
    }
    return (result);
}

sal_uInt32 SAL_CALL rtl_getAppCommandArgCount (void)
{
    if (!g_ppCommandArgs)
        impl_rtl_initCommandArgs();
    return g_nCommandArgCount;
}
<commit_msg>INTEGRATION: CWS warnings01 (1.6.132); FILE MERGED 2005/11/07 19:43:54 pl 1.6.132.3: RESYNC: (1.7-1.8); FILE MERGED 2005/09/23 01:28:05 sb 1.6.132.2: RESYNC: (1.6-1.7); FILE MERGED 2005/08/30 17:03:17 sb 1.6.132.1: #i53898# Made code warning-free.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cmdargs.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 04:29:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <osl/mutex.hxx>
#include <rtl/process.h>
#include <rtl/ustring.hxx>

namespace {

rtl_uString ** g_ppCommandArgs = 0;
sal_uInt32     g_nCommandArgCount = 0;

struct ArgHolder
{
    ~ArgHolder();
};

ArgHolder::~ArgHolder()
{
    while (g_nCommandArgCount > 0)
        rtl_uString_release (g_ppCommandArgs[--g_nCommandArgCount]);

    rtl_freeMemory (g_ppCommandArgs);
    g_ppCommandArgs = 0;
}

// The destructor of this static ArgHolder is "activated" by the assignments to
// g_ppCommandArgs and g_nCommandArgCount in init():
ArgHolder argHolder;

void init()
{
    osl::MutexGuard guard( osl::Mutex::getGlobalMutex() );
    if (!g_ppCommandArgs)
    {
        sal_Int32 i, n = osl_getCommandArgCount();

        g_ppCommandArgs =
            (rtl_uString**)rtl_allocateZeroMemory (n * sizeof(rtl_uString*));
        for (i = 0; i < n; i++)
        {
            rtl_uString * pArg = 0;
            osl_getCommandArg (i, &pArg);
            if (('-' == pArg->buffer[0] || '/' == pArg->buffer[0]) &&
                 'e' == pArg->buffer[1] &&
                 'n' == pArg->buffer[2] &&
                 'v' == pArg->buffer[3] &&
                 ':' == pArg->buffer[4] &&
                rtl_ustr_indexOfChar (&(pArg->buffer[5]), '=') >= 0 )
            {
                // ignore.
                rtl_uString_release (pArg);
            }
            else
            {
                // assign.
                g_ppCommandArgs[g_nCommandArgCount++] = pArg;
            }
        }
    }
}

}

oslProcessError SAL_CALL rtl_getAppCommandArg (
    sal_uInt32 nArg, rtl_uString **ppCommandArg)
{
    init();
    oslProcessError result = osl_Process_E_NotFound;
    if( nArg < g_nCommandArgCount )
    {
         rtl_uString_assign( ppCommandArg, g_ppCommandArgs[nArg] );
        result = osl_Process_E_None;
    }
    return (result);
}

sal_uInt32 SAL_CALL rtl_getAppCommandArgCount (void)
{
    init();
    return g_nCommandArgCount;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Pavel Vainerman.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, version 2.1.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
// --------------------------------------------------------------------------
#include <sstream>
#include <cstdio>
#include <UniSetTypes.h>
#include "PostgreSQLInterface.h"
// --------------------------------------------------------------------------
using namespace std;
using namespace uniset;
using namespace pqxx;
// --------------------------------------------------------------------------

PostgreSQLInterface::PostgreSQLInterface():
	lastQ(""),
	lastE(""),
	last_inserted_id(0)
{
	//db = make_shared<pqxx::connection>();
}

PostgreSQLInterface::~PostgreSQLInterface()
{
	try
	{
		close();
	}
	catch( ... ) // пропускаем все необработанные исключения, если требуется обработать нужно вызывать close() до деструктора
	{
		cerr << "MySQLInterface::~MySQLInterface(): an error occured while closing connection!" << endl;
	}
}

// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::ping() const
{
	if( !db )
		return false;

	try
	{

		nontransaction n(*(db.get()));
		n.exec("select version();");
		return true;
	}
	catch( const std::exception& e )
	{
//		lastE = string(e.what());
	}

	return false;

//	return db && db->is_open();
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::reconnect(const string& host, const string& user, const string& pswd, const string& dbname, unsigned int port )
{
	if( db )
		close();

	return nconnect(host,user,pswd, dbname, port);
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::nconnect(const string& host, const string& user, const string& pswd, const string& dbname, unsigned int port )
{
	if( db )
		return true;

	ostringstream conninfo;
	conninfo << "dbname=" << dbname
			 << " host=" << host
			 << " user=" << user
			 << " password=" << pswd
			 << " port=" << port;

	try
	{
		db = make_shared<pqxx::connection>( std::move(conninfo.str()) );
		return db->is_open();
	}
	catch( const std::exception& e )
	{
		cerr << e.what() << std::endl;
	}

	return false;
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::close()
{
	if( db )
	{
		db->disconnect();
		db.reset();
	}

	return true;
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::copy( const std::string& tblname, const std::vector<std::string>& cols,
								const PostgreSQLInterface::Data& data )
{
	if( !db )
	{
		lastE = "no connection";
		return false;
	}

	try
	{
		work w( *(db.get()) );
		tablewriter t(w, tblname, cols.begin(), cols.end());

		t.reserve(data.size()); // size() не дорогая операция для list?

		for( const auto& d : data )
			t.push_back(d.begin(), d.end());

		t.complete();
		w.commit();
		return true;
	}
	catch( const std::exception& e )
	{
		//cerr << e.what() << std::endl;
		lastE = string(e.what());
	}

	return false;
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::insert( const string& q )
{
	if( !db )
	{
		lastE = "no connection";
		return false;
	}

	try
	{
		work w( *(db.get()) );
		lastQ = q;
		w.exec(q);
		w.commit();
		return true;
	}
	catch( const std::exception& e )
	{
		//cerr << e.what() << std::endl;
		lastE = string(e.what());
	}

	return false;
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::insertAndSaveRowid( const string& q )
{
	if( !db )
	{
		lastE = "no connection";
		return false;
	}

	std::string qplus = q + " RETURNING id";

	try
	{
		work w( *(db.get()) );
		lastQ = q;
		pqxx::result res = w.exec(qplus);
		w.commit();
		save_inserted_id(res);
		return true;
	}
	catch( const std::exception& e )
	{
		//cerr << e.what() << std::endl;
		lastE = string(e.what());
	}

	return false;
}
// -----------------------------------------------------------------------------------------
DBResult PostgreSQLInterface::query( const string& q )
{
	if( !db )
		return DBResult();

	try
	{

		nontransaction n(*(db.get()));
		lastQ = q;
		/* Execute SQL query */
		result res( n.exec(q) );
		return makeResult(res);
	}
	catch( const std::exception& e )
	{
		lastE = string(e.what());
	}

	return DBResult();
}
// -----------------------------------------------------------------------------------------
void PostgreSQLInterface::cancel_query()
{
	if( !db )
		return;

	db->cancel_query();
}
// -----------------------------------------------------------------------------------------
const string PostgreSQLInterface::error()
{
	return lastE;
}
// -----------------------------------------------------------------------------------------
const string PostgreSQLInterface::lastQuery()
{
	return lastQ;
}
// -----------------------------------------------------------------------------------------
double PostgreSQLInterface::insert_id()
{
	return last_inserted_id;
}
// -----------------------------------------------------------------------------------------
void PostgreSQLInterface::save_inserted_id( const pqxx::result& res )
{
	if( res.size() > 0 && res[0].size() > 0 )
		last_inserted_id = res[0][0].as<int>();
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::isConnection() const
{
	return db && ping();
//	return (db && db->is_open())
}
// -----------------------------------------------------------------------------------------
DBResult PostgreSQLInterface::makeResult( const pqxx::result& res )
{
	DBResult result;

	for( result::const_iterator c = res.begin(); c != res.end(); ++c )
	{
		DBResult::COL col;

		for( pqxx::result::tuple::const_iterator i = c.begin(); i != c.end(); i++ )
		{
			if( i.is_null() )
				col.push_back("");
			else
			{
				result.setColName(i.num(), i.name());
				col.push_back( i.as<string>() );
			}
		}

		result.row().push_back( std::move(col) );
	}

	return result;
}
// -----------------------------------------------------------------------------------------
extern "C" std::shared_ptr<DBInterface> create_postgresqlinterface()
{
	return std::shared_ptr<DBInterface>(new PostgreSQLInterface(), DBInterfaceDeleter());
}
// -----------------------------------------------------------------------------------------
<commit_msg>PostgreSQL: used simple query for ping<commit_after>/*
 * Copyright (c) 2015 Pavel Vainerman.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, version 2.1.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
// --------------------------------------------------------------------------
#include <sstream>
#include <cstdio>
#include <UniSetTypes.h>
#include "PostgreSQLInterface.h"
// --------------------------------------------------------------------------
using namespace std;
using namespace uniset;
using namespace pqxx;
// --------------------------------------------------------------------------

PostgreSQLInterface::PostgreSQLInterface():
	lastQ(""),
	lastE(""),
	last_inserted_id(0)
{
	//db = make_shared<pqxx::connection>();
}

PostgreSQLInterface::~PostgreSQLInterface()
{
	try
	{
		close();
	}
	catch( ... ) // пропускаем все необработанные исключения, если требуется обработать нужно вызывать close() до деструктора
	{
		cerr << "MySQLInterface::~MySQLInterface(): an error occured while closing connection!" << endl;
	}
}

// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::ping() const
{
	if( !db )
		return false;

	try
	{

		nontransaction n(*(db.get()));
		n.exec("select 1;");
		return true;
	}
	catch( const std::exception& e )
	{
//		lastE = string(e.what());
	}

	return false;

//	return db && db->is_open();
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::reconnect(const string& host, const string& user, const string& pswd, const string& dbname, unsigned int port )
{
	if( db )
		close();

	return nconnect(host,user,pswd, dbname, port);
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::nconnect(const string& host, const string& user, const string& pswd, const string& dbname, unsigned int port )
{
	if( db )
		return true;

	ostringstream conninfo;
	conninfo << "dbname=" << dbname
			 << " host=" << host
			 << " user=" << user
			 << " password=" << pswd
			 << " port=" << port;

	try
	{
		db = make_shared<pqxx::connection>( std::move(conninfo.str()) );
		return db->is_open();
	}
	catch( const std::exception& e )
	{
		cerr << e.what() << std::endl;
	}

	return false;
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::close()
{
	if( db )
	{
		db->disconnect();
		db.reset();
	}

	return true;
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::copy( const std::string& tblname, const std::vector<std::string>& cols,
								const PostgreSQLInterface::Data& data )
{
	if( !db )
	{
		lastE = "no connection";
		return false;
	}

	try
	{
		work w( *(db.get()) );
		tablewriter t(w, tblname, cols.begin(), cols.end());

		t.reserve(data.size()); // size() не дорогая операция для list?

		for( const auto& d : data )
			t.push_back(d.begin(), d.end());

		t.complete();
		w.commit();
		return true;
	}
	catch( const std::exception& e )
	{
		//cerr << e.what() << std::endl;
		lastE = string(e.what());
	}

	return false;
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::insert( const string& q )
{
	if( !db )
	{
		lastE = "no connection";
		return false;
	}

	try
	{
		work w( *(db.get()) );
		lastQ = q;
		w.exec(q);
		w.commit();
		return true;
	}
	catch( const std::exception& e )
	{
		//cerr << e.what() << std::endl;
		lastE = string(e.what());
	}

	return false;
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::insertAndSaveRowid( const string& q )
{
	if( !db )
	{
		lastE = "no connection";
		return false;
	}

	std::string qplus = q + " RETURNING id";

	try
	{
		work w( *(db.get()) );
		lastQ = q;
		pqxx::result res = w.exec(qplus);
		w.commit();
		save_inserted_id(res);
		return true;
	}
	catch( const std::exception& e )
	{
		//cerr << e.what() << std::endl;
		lastE = string(e.what());
	}

	return false;
}
// -----------------------------------------------------------------------------------------
DBResult PostgreSQLInterface::query( const string& q )
{
	if( !db )
		return DBResult();

	try
	{

		nontransaction n(*(db.get()));
		lastQ = q;
		/* Execute SQL query */
		result res( n.exec(q) );
		return makeResult(res);
	}
	catch( const std::exception& e )
	{
		lastE = string(e.what());
	}

	return DBResult();
}
// -----------------------------------------------------------------------------------------
void PostgreSQLInterface::cancel_query()
{
	if( !db )
		return;

	db->cancel_query();
}
// -----------------------------------------------------------------------------------------
const string PostgreSQLInterface::error()
{
	return lastE;
}
// -----------------------------------------------------------------------------------------
const string PostgreSQLInterface::lastQuery()
{
	return lastQ;
}
// -----------------------------------------------------------------------------------------
double PostgreSQLInterface::insert_id()
{
	return last_inserted_id;
}
// -----------------------------------------------------------------------------------------
void PostgreSQLInterface::save_inserted_id( const pqxx::result& res )
{
	if( res.size() > 0 && res[0].size() > 0 )
		last_inserted_id = res[0][0].as<int>();
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::isConnection() const
{
	return db && ping();
//	return (db && db->is_open())
}
// -----------------------------------------------------------------------------------------
DBResult PostgreSQLInterface::makeResult( const pqxx::result& res )
{
	DBResult result;

	for( result::const_iterator c = res.begin(); c != res.end(); ++c )
	{
		DBResult::COL col;

		for( pqxx::result::tuple::const_iterator i = c.begin(); i != c.end(); i++ )
		{
			if( i.is_null() )
				col.push_back("");
			else
			{
				result.setColName(i.num(), i.name());
				col.push_back( i.as<string>() );
			}
		}

		result.row().push_back( std::move(col) );
	}

	return result;
}
// -----------------------------------------------------------------------------------------
extern "C" std::shared_ptr<DBInterface> create_postgresqlinterface()
{
	return std::shared_ptr<DBInterface>(new PostgreSQLInterface(), DBInterfaceDeleter());
}
// -----------------------------------------------------------------------------------------
<|endoftext|>


<commit_before>#pragma once

#include <cstddef>
#include <iostream>
#include <set>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

namespace ContainerPrinter
{
   namespace Traits
   {
      /**
      * @brief A neat SFINAE trick.
      *
      * @see N3911
      */
      template<class...>
      using void_t = void;

      /**
      * @brief Base case for the testing of STD compatible container types.
      */
      template<
         typename /*Type*/,
         typename = void
      >
      struct is_printable_as_container : std::false_type
      {
      };

      /**
      * @brief Specialization to ensure that Standard Library compatible containers that have
      * `begin()`, `end()`, and `empty()` member functions, as well as the `value_type` and
      * `iterator` typedefs, are treated as printable containers.
      */
      template<typename Type>
      struct is_printable_as_container<
         Type,
         void_t<
         decltype(std::declval<Type&>().begin()),
         decltype(std::declval<Type&>().end()),
         decltype(std::declval<Type&>().empty()),
         typename Type::value_type,
         typename Type::iterator
         >
      > : public std::true_type
      {
      };

      /**
      * @brief Specialization to treat std::pair<...> as a printable container type.
      */
      template<
         typename FirstType,
         typename SecondType
      >
      struct is_printable_as_container<std::pair<FirstType, SecondType>> : public std::true_type
      {
      };

      /**
      * @brief Specialization to treat std::tuple<...> as a printable container type.
      */
      template<typename... DataTypes>
      struct is_printable_as_container<std::tuple<DataTypes...>> : public std::true_type
      {
      };

      /**
      * @brief Specialization to treat arrays as printable container types.
      */
      template<
         typename ArrayType,
         std::size_t ArraySize
      >
      struct is_printable_as_container<ArrayType[ArraySize]> : public std::true_type
      {
      };

      /**
      * @brief Narrow character array specialization in order to ensure that we print character arrays
      * as string and not as delimiter containers.
      */
      template<std::size_t ArraySize>
      struct is_printable_as_container<char[ArraySize]> : public std::false_type
      {
      };

      /**
      * @brief Wide character array specialization in order to ensure that we print character arrays
      * as string and not as delimiter containers.
      */
      template<std::size_t ArraySize>
      struct is_printable_as_container<wchar_t[ArraySize]> : public std::false_type
      {
      };

      /**
      * @brief String specialization in order to ensure that we treat strings as nothing more than strings.
      */
      template<
         typename CharacterType,
         typename CharacterTraitsType,
         typename AllocatorType
      >
      struct is_printable_as_container<
         std::basic_string<
         CharacterType,
         CharacterTraitsType,
         AllocatorType
         >
      > : public std::false_type
      {
      };

      /**
      * @brief Helper variable template.
      */
      template<typename Type>
      constexpr bool is_printable_as_container_v = is_printable_as_container<Type>::value;
   }

   /**
   * @brief Struct to neatly wrap up all the additional characters we'll need in order to
   * print out the containers.
   */
   template<typename CharacterType>
   struct delimiter_values
   {
      using type = CharacterType;

      const type* prefix;
      const type* separator;
      const type* suffix;
   };

   /**
   * @brief Additional wrapper around the `delimiter_values` struct for added convenience.
   */
   template<
      typename /*ContainerType*/,
      typename CharacterType
   >
   struct delimiters
   {
      using type = delimiter_values<CharacterType>;

      static const type values;
   };

   /**
   * @brief Default narrow delimiters for any container type that isn't specialized.
   */
   template<typename ContainerType>
   struct delimiters<ContainerType, char>
   {
      using type = delimiter_values<char>;

      static constexpr type values = { "[", ", ", "]" };
   };

   /**
   * @brief Default wide delimiters for any container type that isn't specialized.
   */
   template<typename ContainerType>
   struct delimiters<ContainerType, wchar_t>
   {
      using type = delimiter_values<wchar_t>;

      static constexpr type values = { L"[", L", ", L"]" };
   };

   /**
   * @brief Narrow character specialization for std::set<...>.
   */
   template<
      typename DataType,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::set<DataType, ComparatorType, AllocatorType>, char>
   {
      static constexpr delimiter_values<char> values = { "{", ", ", "}" };
   };

   /**
   * @brief Wide character specialization for std::set<...>.
   */
   template<
      typename DataType,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::set<DataType, ComparatorType, AllocatorType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"{", L", ", L"}" };
   };

   /**
   * @brief Narrow character specialization for std::multiset<...>.
   */
   template<
      typename DataType,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::multiset<DataType, ComparatorType, AllocatorType>, char>
   {
      static constexpr delimiter_values<char> values = { "{", ", ", "}" };
   };

   /**
   * @brief Wide character specialization for std::multiset<...>.
   */
   template<
      typename DataType,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::multiset<DataType, ComparatorType, AllocatorType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"{", L", ", L"}" };
   };

   /**
   * @brief Narrow character specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct delimiters<std::pair<FirstType, SecondType>, char>
   {
      static constexpr delimiter_values<char> values = { "(", ", ", ")" };
   };

   /**
   * @brief Wide character specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct delimiters<std::pair<FirstType, SecondType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"(", L", ", L")" };
   };

   /**
   * @brief Narrow character specialization for std::tuple<...>.
   */
   template<typename... DataType>
   struct delimiters<std::tuple<DataType...>, char>
   {
      static constexpr delimiter_values<char> values = { "<", ", ", ">" };
   };

   /**
   * @brief Wide character specialization for std::tuple<...>.
   */
   template<typename... DataType>
   struct delimiters<std::tuple<DataType...>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"<", L", ", L">" };
   };

   /**
   * @brief Recursive tuple helper template to print std::tuple<...> objects.
   */
   template<
      typename TupleType,
      std::size_t N
   >
   struct tuple_printer
   {
      template<
         typename CharacterType,
         typename CharacterTraitsType,
         typename DelimiterValues
      >
      inline static void print(
         std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
         const TupleType& container,
         const DelimiterValues& delimiters)
      {
         tuple_printer<TupleType, N - 1>::print(stream, container, delimiters);

         stream
            << delimiters.separator
            << std::get<N - 1>(container);
      }
   };

   /**
   * @brief Specialization of tuple helper to handle empty std::tuple<...> objects.
   */
   template<typename TupleType>
   struct tuple_printer<TupleType, 0>
   {
      template<
         typename CharacterType,
         typename CharacterTraitsType,
         typename DelimiterValues
      >
      inline static void print(
         std::basic_ostream<CharacterType, CharacterTraitsType>& /*stream*/,
         const TupleType& /*tuple*/,
         const DelimiterValues& /*delimiters*/)
      {
      };
   };

   /**
   * @brief Specialization of tuple helper for the first index of a std::tuple<...>
   */
   template<typename TupleType>
   struct tuple_printer<TupleType, 1>
   {
      template<
         typename CharacterType,
         typename CharacterTraitsType,
         typename DelimiterValues
      >
      inline static void print(
         std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
         const TupleType& tuple,
         const DelimiterValues& /*delimiters*/)
      {
         stream << std::get<0>(tuple);
      }
   };

   /**
   * @brief Specialization for non-zero indices of a std::tuple<...>.
   */
   template<
      typename CharacterType,
      typename CharacterTraitsType,
      typename... TupleArgs
   >
   inline static void printing_helper(
      std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
      const std::tuple<TupleArgs...>& container)
   {
      static constexpr auto delimiters =
         ContainerPrinter::delimiters<
            std::decay_t<decltype(container)>,
            CharacterType
         >::values;

      stream << delimiters.prefix;
      tuple_printer<decltype(container), sizeof...(TupleArgs)>::print(stream, container, delimiters);
      stream << delimiters.suffix;
   }

   /**
   * @brief Helper function to determine if a container is empty.
   */
   template<typename ContainerType>
   inline bool is_empty(const ContainerType& container)
   {
      return container.empty();
   };

   /**
   * @brief Helper function to be selected for non-empty arrays.
   */
   template<
      typename ArrayType,
      std::size_t ArraySize
   >
   constexpr bool is_empty(const ArrayType(&)[ArraySize])
   {
      return false;
   }

   /**
   * @brief Helper function to be selected for empty arrays.
   */
   template<
      typename ArrayType,
      std::size_t /*ArraySize*/
   >
   constexpr bool is_empty(const ArrayType(&)[0])
   {
      return true;
   }

   /**
   * @brief Printing specialization suitable for most container types.
   */
   template<
      typename ContainerType,
      typename CharacterTraitsType,
      typename TraitsType
   >
   inline static void printing_helper(
      std::basic_ostream<CharacterTraitsType, TraitsType>& stream,
      const ContainerType& container)
   {
      static constexpr auto delimiters =
         ContainerPrinter::delimiters<
            ContainerType,
            CharacterTraitsType
         >::values;

      if (is_empty(container))
      {
         stream
            << delimiters.prefix
            << delimiters.suffix;

         return;
      }

      auto begin = std::begin(container);
      stream << delimiters.prefix << *begin;
      std::advance(begin, 1);

      std::for_each(begin, std::end(container),
         [&stream] (const auto& value)
      {
         stream << delimiters.separator << value;
      });

      stream << delimiters.suffix;
   }

   /**
   * @brief Printing specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType,
      typename CharacterType,
      typename CharacterTraitsType
   >
   inline static void printing_helper(
      std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
      const std::pair<FirstType, SecondType>& container)
   {
      static constexpr auto delimiters =
         ContainerPrinter::delimiters<
            std::decay_t<decltype(container)>,
            CharacterType
         >::values;

      stream
         << delimiters.prefix
         << container.first
         << delimiters.separator
         << container.second
         << delimiters.suffix;
   }

   /**
   * @brief Main class that will print out the container with the help of various templated
   * helper functions.
   */
   template<
      typename ContainerType,
      typename CharacterType,
      typename CharacterTraitsType
   >
   class Printer
   {
   public:
      Printer(const ContainerType& container)
         : m_container{ container }
      {
      }

      inline void print_to(std::basic_ostream<CharacterType, CharacterTraitsType>& stream) const
      {
         printing_helper(stream, m_container);
      }

   private:
      const ContainerType& m_container;
   };
}

/**
* @brief Overload of the stream output operator for compatible containers.
*/
template<
   typename ContainerType,
   typename CharacterType,
   typename CharacterTraitsType,
   typename = std::enable_if_t<ContainerPrinter::Traits::is_printable_as_container_v<ContainerType>>
>
auto& operator<<(
   std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
   const ContainerType& container)
{
   ContainerPrinter::Printer<
      ContainerType,
      CharacterType,
      CharacterTraitsType
   >(container).print_to(stream);

   return stream;
}
<commit_msg>Formatting<commit_after>#pragma once

#include <cstddef>
#include <iostream>
#include <set>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

namespace ContainerPrinter
{
   namespace Traits
   {
      /**
      * @brief A neat SFINAE trick.
      *
      * @see N3911
      */
      template<class...>
      using void_t = void;

      /**
      * @brief Base case for the testing of STD compatible container types.
      */
      template<
         typename /*Type*/,
         typename = void
      >
      struct is_printable_as_container : std::false_type
      {
      };

      /**
      * @brief Specialization to ensure that Standard Library compatible containers that have
      * `begin()`, `end()`, and `empty()` member functions, as well as the `value_type` and
      * `iterator` typedefs, are treated as printable containers.
      */
      template<typename Type>
      struct is_printable_as_container<
         Type,
         void_t<
            decltype(std::declval<Type&>().begin()),
            decltype(std::declval<Type&>().end()),
            decltype(std::declval<Type&>().empty()),
            typename Type::value_type,
            typename Type::iterator
         >
      > : public std::true_type
      {
      };

      /**
      * @brief Specialization to treat std::pair<...> as a printable container type.
      */
      template<
         typename FirstType,
         typename SecondType
      >
      struct is_printable_as_container<std::pair<FirstType, SecondType>> : public std::true_type
      {
      };

      /**
      * @brief Specialization to treat std::tuple<...> as a printable container type.
      */
      template<typename... DataTypes>
      struct is_printable_as_container<std::tuple<DataTypes...>> : public std::true_type
      {
      };

      /**
      * @brief Specialization to treat arrays as printable container types.
      */
      template<
         typename ArrayType,
         std::size_t ArraySize
      >
      struct is_printable_as_container<ArrayType[ArraySize]> : public std::true_type
      {
      };

      /**
      * @brief Narrow character array specialization in order to ensure that we print character arrays
      * as string and not as delimiter containers.
      */
      template<std::size_t ArraySize>
      struct is_printable_as_container<char[ArraySize]> : public std::false_type
      {
      };

      /**
      * @brief Wide character array specialization in order to ensure that we print character arrays
      * as string and not as delimiter containers.
      */
      template<std::size_t ArraySize>
      struct is_printable_as_container<wchar_t[ArraySize]> : public std::false_type
      {
      };

      /**
      * @brief String specialization in order to ensure that we treat strings as nothing more than strings.
      */
      template<
         typename CharacterType,
         typename CharacterTraitsType,
         typename AllocatorType
      >
      struct is_printable_as_container<
         std::basic_string<
            CharacterType,
            CharacterTraitsType,
            AllocatorType
         >
      > : public std::false_type
      {
      };

      /**
      * @brief Helper variable template.
      */
      template<typename Type>
      constexpr bool is_printable_as_container_v = is_printable_as_container<Type>::value;
   }

   /**
   * @brief Struct to neatly wrap up all the additional characters we'll need in order to
   * print out the containers.
   */
   template<typename CharacterType>
   struct delimiter_values
   {
      using type = CharacterType;

      const type* prefix;
      const type* separator;
      const type* suffix;
   };

   /**
   * @brief Additional wrapper around the `delimiter_values` struct for added convenience.
   */
   template<
      typename /*ContainerType*/,
      typename CharacterType
   >
   struct delimiters
   {
      using type = delimiter_values<CharacterType>;

      static const type values;
   };

   /**
   * @brief Default narrow delimiters for any container type that isn't specialized.
   */
   template<typename ContainerType>
   struct delimiters<ContainerType, char>
   {
      using type = delimiter_values<char>;

      static constexpr type values = { "[", ", ", "]" };
   };

   /**
   * @brief Default wide delimiters for any container type that isn't specialized.
   */
   template<typename ContainerType>
   struct delimiters<ContainerType, wchar_t>
   {
      using type = delimiter_values<wchar_t>;

      static constexpr type values = { L"[", L", ", L"]" };
   };

   /**
   * @brief Narrow character specialization for std::set<...>.
   */
   template<
      typename DataType,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::set<DataType, ComparatorType, AllocatorType>, char>
   {
      static constexpr delimiter_values<char> values = { "{", ", ", "}" };
   };

   /**
   * @brief Wide character specialization for std::set<...>.
   */
   template<
      typename DataType,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::set<DataType, ComparatorType, AllocatorType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"{", L", ", L"}" };
   };

   /**
   * @brief Narrow character specialization for std::multiset<...>.
   */
   template<
      typename DataType,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::multiset<DataType, ComparatorType, AllocatorType>, char>
   {
      static constexpr delimiter_values<char> values = { "{", ", ", "}" };
   };

   /**
   * @brief Wide character specialization for std::multiset<...>.
   */
   template<
      typename DataType,
      typename ComparatorType,
      typename AllocatorType
   >
   struct delimiters<std::multiset<DataType, ComparatorType, AllocatorType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"{", L", ", L"}" };
   };

   /**
   * @brief Narrow character specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct delimiters<std::pair<FirstType, SecondType>, char>
   {
      static constexpr delimiter_values<char> values = { "(", ", ", ")" };
   };

   /**
   * @brief Wide character specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType
   >
   struct delimiters<std::pair<FirstType, SecondType>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"(", L", ", L")" };
   };

   /**
   * @brief Narrow character specialization for std::tuple<...>.
   */
   template<typename... DataType>
   struct delimiters<std::tuple<DataType...>, char>
   {
      static constexpr delimiter_values<char> values = { "<", ", ", ">" };
   };

   /**
   * @brief Wide character specialization for std::tuple<...>.
   */
   template<typename... DataType>
   struct delimiters<std::tuple<DataType...>, wchar_t>
   {
      static constexpr delimiter_values<wchar_t> values = { L"<", L", ", L">" };
   };

   /**
   * @brief Recursive tuple helper template to print std::tuple<...> objects.
   */
   template<
      typename TupleType,
      std::size_t Index
   >
   struct tuple_printer
   {
      template<
         typename CharacterType,
         typename CharacterTraitsType,
         typename DelimiterValues
      >
      inline static void print(
         std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
         const TupleType& container,
         const DelimiterValues& delimiters)
      {
         tuple_printer<TupleType, Index - 1>::print(stream, container, delimiters);

         stream
            << delimiters.separator
            << std::get<Index - 1>(container);
      }
   };

   /**
   * @brief Specialization of tuple helper to handle empty std::tuple<...> objects.
   */
   template<typename TupleType>
   struct tuple_printer<TupleType, 0>
   {
      template<
         typename CharacterType,
         typename CharacterTraitsType,
         typename DelimiterValues
      >
      inline static void print(
         std::basic_ostream<CharacterType, CharacterTraitsType>& /*stream*/,
         const TupleType& /*tuple*/,
         const DelimiterValues& /*delimiters*/)
      {
      };
   };

   /**
   * @brief Specialization of tuple helper for the first index of a std::tuple<...>
   */
   template<typename TupleType>
   struct tuple_printer<TupleType, 1>
   {
      template<
         typename CharacterType,
         typename CharacterTraitsType,
         typename DelimiterValues
      >
      inline static void print(
         std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
         const TupleType& tuple,
         const DelimiterValues& /*delimiters*/)
      {
         stream << std::get<0>(tuple);
      }
   };

   /**
   * @brief Specialization for non-zero indices of a std::tuple<...>.
   */
   template<
      typename CharacterType,
      typename CharacterTraitsType,
      typename... TupleArgs
   >
   inline static void printing_helper(
      std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
      const std::tuple<TupleArgs...>& container)
   {
      static constexpr auto delimiters =
         ContainerPrinter::delimiters<
            std::decay_t<decltype(container)>,
            CharacterType
         >::values;

      stream << delimiters.prefix;
      tuple_printer<decltype(container), sizeof...(TupleArgs)>::print(stream, container, delimiters);
      stream << delimiters.suffix;
   }

   /**
   * @brief Helper function to determine if a container is empty.
   */
   template<typename ContainerType>
   inline bool is_empty(const ContainerType& container)
   {
      return container.empty();
   };

   /**
   * @brief Helper function to be selected for non-empty arrays.
   */
   template<
      typename ArrayType,
      std::size_t ArraySize
   >
   constexpr bool is_empty(const ArrayType(&)[ArraySize])
   {
      return false;
   }

   /**
   * @brief Helper function to be selected for empty arrays.
   */
   template<
      typename ArrayType,
      std::size_t /*ArraySize*/
   >
   constexpr bool is_empty(const ArrayType(&)[0])
   {
      return true;
   }

   /**
   * @brief Printing specialization suitable for most container types.
   */
   template<
      typename ContainerType,
      typename CharacterTraitsType,
      typename TraitsType
   >
   inline static void printing_helper(
      std::basic_ostream<CharacterTraitsType, TraitsType>& stream,
      const ContainerType& container)
   {
      static constexpr auto delimiters =
         ContainerPrinter::delimiters<
            ContainerType,
            CharacterTraitsType
         >::values;

      if (is_empty(container))
      {
         stream
            << delimiters.prefix
            << delimiters.suffix;

         return;
      }

      auto begin = std::begin(container);
      stream << delimiters.prefix << *begin;
      std::advance(begin, 1);

      std::for_each(begin, std::end(container),
         [&stream] (const auto& value)
      {
         stream << delimiters.separator << value;
      });

      stream << delimiters.suffix;
   }

   /**
   * @brief Printing specialization for std::pair<...>.
   */
   template<
      typename FirstType,
      typename SecondType,
      typename CharacterType,
      typename CharacterTraitsType
   >
   inline static void printing_helper(
      std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
      const std::pair<FirstType, SecondType>& container)
   {
      static constexpr auto delimiters =
         ContainerPrinter::delimiters<
            std::decay_t<decltype(container)>,
            CharacterType
         >::values;

      stream
         << delimiters.prefix
         << container.first
         << delimiters.separator
         << container.second
         << delimiters.suffix;
   }

   /**
   * @brief Main class that will print out the container with the help of various templated
   * helper functions.
   */
   template<
      typename ContainerType,
      typename CharacterType,
      typename CharacterTraitsType
   >
   class Printer
   {
   public:
      Printer(const ContainerType& container)
         : m_container{ container }
      {
      }

      inline void print_to(std::basic_ostream<CharacterType, CharacterTraitsType>& stream) const
      {
         printing_helper(stream, m_container);
      }

   private:
      const ContainerType& m_container;
   };
}

/**
* @brief Overload of the stream output operator for compatible containers.
*/
template<
   typename ContainerType,
   typename CharacterType,
   typename CharacterTraitsType,
   typename = std::enable_if_t<ContainerPrinter::Traits::is_printable_as_container_v<ContainerType>>
>
auto& operator<<(
   std::basic_ostream<CharacterType, CharacterTraitsType>& stream,
   const ContainerType& container)
{
   ContainerPrinter::Printer<
      ContainerType,
      CharacterType,
      CharacterTraitsType
   >(container).print_to(stream);

   return stream;
}
<|endoftext|>


<commit_before><commit_msg>Fix refreshing problem in folder view (Bug#11688, Bug#9366)<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <float.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <CL/opencl.h>
#include <algorithm>
#include "params.h"

#define CL_USE_DEPRECATED_OPENCL_1_1_APIS //to solve compatibility issues b/w various OCL libraries

typedef struct record
{
  char recString[REC_LENGTH];
  float distance;
} Record;

void findLowest(std::vector<Record> &records,float *distances,int *minLocations,int topN) {
  int i;
  float val;
  int minLoc1;
  Record *tempRec;

  for(i=0;i<topN;i++) {
    minLoc1 = minLocations[i];

    // swap locations
    tempRec = &records[i];
    records[i] = records[minLoc1];
    records[minLoc1] = *tempRec;

    // add distance to the min we found
    records[i].distance = distances[i];
  }
}

int load_file_to_memory(const char *filename, char **result) {
  size_t size = 0;
  FILE *f = fopen(filename, "rb");
  if (f == NULL)
  {
    *result = NULL;
    return -1; // -1 means file opening fail
  }
  fseek(f, 0, SEEK_END);
  size = ftell(f);
  fseek(f, 0, SEEK_SET);
  *result = (char *)malloc(size+1);
  if (size != fread(*result, sizeof(char), size, f))
  {
    free(*result);
    return -2; // -2 means file reading fail
  }
  fclose(f);
  (*result)[size] = 0;
  return size;
}

int main(int argc, char *argv[]) {
  std::vector<Record> records;
  std::vector<cl_float2> locations;
  int i;
  char filename[1024];
  int resultsCount=NUM_NEIGHBORS,quiet=0;
  float lat=QUERY_LAT,lng=QUERY_LNG;

  cl_context context;
  cl_context_properties properties[3];
  cl_kernel kernel1;
  cl_kernel kernel2;
  cl_command_queue command_queue;
  cl_program program;
  cl_int err;
  cl_uint num_of_platforms=0;
  cl_platform_id platform_id;
  cl_device_id device_id;
  cl_uint num_of_devices=0;

  FILE *fp;
  int numRecords=0;
  fp = fopen("../../../../../data/filelist.txt", "r");
  if(!fp) {
    perror("error opening the data file\n");
    exit(1);
  }
        // read each record
  while(!feof(fp)){
    Record record;
    cl_float2 latLong;
    fgets(record.recString,REC_LENGTH,fp);
    fgetc(fp); // newline
    if (feof(fp)) break;

    // parse for lat and long
    char str[REC_LENGTH];
    strncpy(str,record.recString,sizeof(str));
    int year, month, date, hour, num, speed, press;
    float lat, lon;
    char name[REC_LENGTH];
    sscanf(str, "%d %d %d %d %d %s %f %f %d %d", &year,
      &month, &date, &hour, &num, name, &lat,   &lon, &speed, &press);
    latLong.x = lat;
    latLong.y = lon;

    locations.push_back(latLong);
    records.push_back(record);
    numRecords++;
  }
  fclose(fp);

  if (!quiet) {
    printf("Number of records: %d\n",numRecords);
    printf("latitude: %f\n",lat);
    printf("longitude: %f\n",lng);
    printf("Finding the %d closest neighbors.\n",resultsCount);
  }

  if (resultsCount > numRecords) resultsCount = numRecords;

  // retreive a list of platforms avaible
  if (clGetPlatformIDs(1, &platform_id, &num_of_platforms)!= CL_SUCCESS) {
    printf("Unable to get platform_id\n");
    return 1;
  }

  // connect to a compute device
  if (clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ACCELERATOR, 1,
    &device_id, &num_of_devices) != CL_SUCCESS) {
    printf("Unable to get device_id\n");
    return 1;
  }

  // context properties list - must be terminated with 0
  properties[0]= CL_CONTEXT_PLATFORM;
  properties[1]= (cl_context_properties) platform_id;
  properties[2]= 0;

  // create a context with the FPGA device
  context = clCreateContext(properties,1,&device_id,NULL,NULL,&err);

  // create command queue using the context and device
  command_queue = clCreateCommandQueue(context, device_id, 0, &err);

  int status;
  unsigned char *kernelbinary;
  char *xclbin=argv[1];
  printf("loading %s\n", xclbin);
  int n_i = load_file_to_memory(xclbin, (char **) &kernelbinary);
  if (n_i < 0) {
    printf("failed to load kernel from xclbin: %s\n", xclbin);
    printf("Test failed\n");
    return EXIT_FAILURE;
  }
  size_t n = n_i;

  // Create the compute program from offline
  program = clCreateProgramWithBinary(context, 1, &device_id, &n,
    (const unsigned char **) &kernelbinary, &status, &err);

  // compile the program
  if (clBuildProgram(program, 0, NULL, NULL, NULL, NULL) != CL_SUCCESS) {
    printf("Error building program\n");
    return 1;
  }

  // specify which kernel from the program to execute
  kernel1 = clCreateKernel(program, "distance_calc", &err);
  kernel2 = clCreateKernel(program, "NearestNeighbor", &err);

  // create buffers for the input and ouput
  cl_mem d_locations;
  cl_mem d_distances;
  cl_mem indices;

  d_locations = clCreateBuffer(context, CL_MEM_READ_ONLY,
    sizeof(cl_float2) * numRecords, NULL, NULL);
  d_distances = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
    sizeof(float) * resultsCount, NULL, NULL);
  indices = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
    sizeof(int) * resultsCount, NULL, NULL);

  // load data into the input buffer
  clEnqueueWriteBuffer(command_queue, d_locations, CL_TRUE, 0,
    sizeof(cl_float2) * numRecords, &locations[0], 0, NULL, NULL);

  // set the argument list for the kernel1 command
  clSetKernelArg(kernel1, 0, sizeof(cl_mem), (void *)&d_locations);
  clSetKernelArg(kernel1, 1, sizeof(float), (void *)&lat);
  clSetKernelArg(kernel1, 2, sizeof(float), (void *)&lng);

  // enqueue kernel for execution
  size_t globalWorkSize1[1];
  size_t local1[1];
  local1[0] = WORK_GROUP_SIZE;
  globalWorkSize1[0] = numRecords;//Total number of work items to execute a kernel
  if (numRecords % 64) globalWorkSize1[0] += 64 - (numRecords % 64);

  clEnqueueNDRangeKernel(command_queue, kernel1, 1, NULL,
    (size_t*)&globalWorkSize1, (size_t*)&local1, 0, NULL, NULL);

  // set the argument list for the kernel2 command
  clSetKernelArg(kernel2, 0, sizeof(cl_mem), (void *)&d_distances);
  clSetKernelArg(kernel2, 1, sizeof(cl_mem), (void *)&indices);
  clSetKernelArg(kernel2, 2, sizeof(int), (void *)&resultsCount);

  // enqueue kernel for execution
  size_t globalWorkSize2[1];
  size_t local2[1];
  local2[0] = WORK_GROUP_SIZE;
  globalWorkSize2[0] = numRecords;//Total number of work items to execute a kernel
  if (numRecords % 64) globalWorkSize2[0] += 64 - (numRecords % 64);

  clEnqueueNDRangeKernel(command_queue, kernel2, 1, NULL,
    (size_t*)&globalWorkSize2, (size_t*)&local2, 0, NULL, NULL);

  // transfer the results from the output buffer
  float *distances = (float *)malloc(sizeof(float) * resultsCount);
  int *minLocations_final = (int *)malloc(sizeof(int) * resultsCount);

  clEnqueueReadBuffer(command_queue, d_distances, CL_TRUE, 0,
    sizeof(float) * resultsCount, distances, 0, NULL, NULL);
  clEnqueueReadBuffer(command_queue, indices, CL_TRUE, 0,
    sizeof(int) * resultsCount, minLocations_final, 0, NULL, NULL);

  // return finalized data and release buffers
  clReleaseMemObject(d_locations);
  clReleaseMemObject(d_distances);
  clReleaseMemObject(indices);
  clReleaseProgram(program);
  clReleaseKernel(kernel1);
  clReleaseKernel(kernel2);
  clReleaseCommandQueue(command_queue);
  clReleaseContext(context);

  // find the resultsCount least distances
  findLowest(records,distances,minLocations_final,resultsCount);

  // print out results
  if (!quiet)
    for(i=0;i<resultsCount;i++) {
      printf("%s --> Distance=%f\n",records[i].recString,records[i].distance);
    }
  return 0;
}

<commit_msg>Update main_fpga.cpp<commit_after>#include <iostream>
#include <vector>
#include <float.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <CL/opencl.h>
#include <algorithm>
#include "params.h"

#define CL_USE_DEPRECATED_OPENCL_1_1_APIS //to solve compatibility issues b/w various OCL libraries

typedef struct record
{
  char recString[REC_LENGTH];
  float distance;
} Record;

void findLowest(std::vector<Record> &records,float *distances,int *minLocations,int topN) {
  int i;
  float val;
  int minLoc1;
  Record *tempRec;

  for(i=0;i<topN;i++) {
    minLoc1 = minLocations[i];

    // swap locations
    tempRec = &records[i];
    records[i] = records[minLoc1];
    records[minLoc1] = *tempRec;

    // add distance to the min we found
    records[i].distance = distances[i];
  }
}

int load_file_to_memory(const char *filename, char **result) {
  size_t size = 0;
  FILE *f = fopen(filename, "rb");
  if (f == NULL)
  {
    *result = NULL;
    return -1; // -1 means file opening fail
  }
  fseek(f, 0, SEEK_END);
  size = ftell(f);
  fseek(f, 0, SEEK_SET);
  *result = (char *)malloc(size+1);
  if (size != fread(*result, sizeof(char), size, f))
  {
    free(*result);
    return -2; // -2 means file reading fail
  }
  fclose(f);
  (*result)[size] = 0;
  return size;
}

int main(int argc, char *argv[]) {
  std::vector<Record> records;
  std::vector<cl_float2> locations;
  int i;
  char filename[1024];
  int resultsCount=NUM_NEIGHBORS,quiet=0;
  float lat=QUERY_LAT,lng=QUERY_LNG;

  cl_context context;
  cl_context_properties properties[3];
  cl_kernel kernel1;
  cl_kernel kernel2;
  cl_command_queue command_queue;
  cl_program program;
  cl_int err;
  cl_uint num_of_platforms=0;
  cl_platform_id platform_id;
  cl_device_id device_id;
  cl_uint num_of_devices=0;

  FILE *fp;
  int numRecords=0;
  fp = fopen("../../../../../data/filelist.txt", "r");
  if(!fp) {
    perror("error opening the data file\n");
    exit(1);
  }
        // read each record
  while(!feof(fp)){
    Record record;
    cl_float2 latLong;
    fgets(record.recString,REC_LENGTH,fp);
    fgetc(fp); // newline
    if (feof(fp)) break;

    // parse for lat and long
    char str[REC_LENGTH];
    strncpy(str,record.recString,sizeof(str));
    int year, month, date, hour, num, speed, press;
    float lat, lon;
    char name[REC_LENGTH];
    sscanf(str, "%d %d %d %d %d %s %f %f %d %d", &year,
      &month, &date, &hour, &num, name, &lat,   &lon, &speed, &press);
    latLong.x = lat;
    latLong.y = lon;

    locations.push_back(latLong);
    records.push_back(record);
    numRecords++;
  }
  fclose(fp);

  if (!quiet) {
    printf("Number of points in reference data set: %d\n",numRecords);
    printf("latitude: %f\n",lat);
    printf("longitude: %f\n",lng);
    printf("Finding the %d closest neighbors.\n",resultsCount);
  }

  if (resultsCount > numRecords) resultsCount = numRecords;

  // retreive a list of platforms avaible
  if (clGetPlatformIDs(1, &platform_id, &num_of_platforms)!= CL_SUCCESS) {
    printf("Unable to get platform_id\n");
    return 1;
  }

  // connect to a compute device
  if (clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_ACCELERATOR, 1,
    &device_id, &num_of_devices) != CL_SUCCESS) {
    printf("Unable to get device_id\n");
    return 1;
  }

  // context properties list - must be terminated with 0
  properties[0]= CL_CONTEXT_PLATFORM;
  properties[1]= (cl_context_properties) platform_id;
  properties[2]= 0;

  // create a context with the FPGA device
  context = clCreateContext(properties,1,&device_id,NULL,NULL,&err);

  // create command queue using the context and device
  command_queue = clCreateCommandQueue(context, device_id, 0, &err);

  int status;
  unsigned char *kernelbinary;
  char *xclbin=argv[1];
  printf("loading %s\n", xclbin);
  int n_i = load_file_to_memory(xclbin, (char **) &kernelbinary);
  if (n_i < 0) {
    printf("failed to load kernel from xclbin: %s\n", xclbin);
    printf("Test failed\n");
    return EXIT_FAILURE;
  }
  size_t n = n_i;

  // Create the compute program from offline
  program = clCreateProgramWithBinary(context, 1, &device_id, &n,
    (const unsigned char **) &kernelbinary, &status, &err);

  // compile the program
  if (clBuildProgram(program, 0, NULL, NULL, NULL, NULL) != CL_SUCCESS) {
    printf("Error building program\n");
    return 1;
  }

  // specify which kernel from the program to execute
  kernel1 = clCreateKernel(program, "distance_calc", &err);
  kernel2 = clCreateKernel(program, "NearestNeighbor", &err);

  // create buffers for the input and ouput
  cl_mem d_locations;
  cl_mem d_distances;
  cl_mem indices;

  d_locations = clCreateBuffer(context, CL_MEM_READ_ONLY,
    sizeof(cl_float2) * numRecords, NULL, NULL);
  d_distances = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
    sizeof(float) * resultsCount, NULL, NULL);
  indices = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
    sizeof(int) * resultsCount, NULL, NULL);

  // load data into the input buffer
  clEnqueueWriteBuffer(command_queue, d_locations, CL_TRUE, 0,
    sizeof(cl_float2) * numRecords, &locations[0], 0, NULL, NULL);

  // set the argument list for the kernel1 command
  clSetKernelArg(kernel1, 0, sizeof(cl_mem), (void *)&d_locations);
  clSetKernelArg(kernel1, 1, sizeof(float), (void *)&lat);
  clSetKernelArg(kernel1, 2, sizeof(float), (void *)&lng);

  // enqueue kernel for execution
  size_t globalWorkSize1[1];
  size_t local1[1];
  local1[0] = WORK_GROUP_SIZE;
  globalWorkSize1[0] = numRecords;//Total number of work items to execute a kernel

  clEnqueueNDRangeKernel(command_queue, kernel1, 1, NULL,
    (size_t*)&globalWorkSize1, (size_t*)&local1, 0, NULL, NULL);

  // set the argument list for the kernel2 command
  clSetKernelArg(kernel2, 0, sizeof(cl_mem), (void *)&d_distances);
  clSetKernelArg(kernel2, 1, sizeof(cl_mem), (void *)&indices);
  clSetKernelArg(kernel2, 2, sizeof(int), (void *)&resultsCount);

  // enqueue kernel for execution
  size_t globalWorkSize2[1];
  size_t local2[1];
  local2[0] = WORK_GROUP_SIZE;
  globalWorkSize2[0] = numRecords;//Total number of work items to execute a kernel

  clEnqueueNDRangeKernel(command_queue, kernel2, 1, NULL,
    (size_t*)&globalWorkSize2, (size_t*)&local2, 0, NULL, NULL);

  // transfer the results from the output buffer
  float *distances = (float *)malloc(sizeof(float) * resultsCount);
  int *minLocations_final = (int *)malloc(sizeof(int) * resultsCount);

  clEnqueueReadBuffer(command_queue, d_distances, CL_TRUE, 0,
    sizeof(float) * resultsCount, distances, 0, NULL, NULL);
  clEnqueueReadBuffer(command_queue, indices, CL_TRUE, 0,
    sizeof(int) * resultsCount, minLocations_final, 0, NULL, NULL);

  // return finalized data and release buffers
  clReleaseMemObject(d_locations);
  clReleaseMemObject(d_distances);
  clReleaseMemObject(indices);
  clReleaseProgram(program);
  clReleaseKernel(kernel1);
  clReleaseKernel(kernel2);
  clReleaseCommandQueue(command_queue);
  clReleaseContext(context);

  // find the resultsCount least distances
  findLowest(records,distances,minLocations_final,resultsCount);

  // print out results
  if (!quiet)
    for(i=0;i<resultsCount;i++) {
      printf("%s --> Distance=%f\n",records[i].recString,records[i].distance);
    }
  return 0;
}

<|endoftext|>


<commit_before>#include "line_splitter.hh"

namespace Moses2
{

line_text splitLine(const StringPiece &textin)
{
  const char delim[] = "|||";
  line_text output;

  //Tokenize
  util::TokenIter<util::MultiCharacter> it(textin, util::MultiCharacter(delim));
  //Get source phrase
  output.source_phrase = Trim(*it);
  //std::cerr << "output.source_phrase=" << output.source_phrase << "AAAA" << std::endl;

  //Get target_phrase
  it++;
  output.target_phrase = Trim(*it);
  //std::cerr << "output.target_phrase=" << output.target_phrase << "AAAA" << std::endl;

  //Get probabilities
  it++;
  output.prob = Trim(*it);
  //std::cerr << "output.prob=" << output.prob << "AAAA" << std::endl;

  //Get WordAllignment
  it++;
  if (it == util::TokenIter<util::MultiCharacter>::end()) return output;
  output.word_align = Trim(*it);
  //std::cerr << "output.word_align=" << output.word_align << "AAAA" << std::endl;

  //Get count
  it++;
  if (it == util::TokenIter<util::MultiCharacter>::end()) return output;
  output.counts = Trim(*it);
  //std::cerr << "output.counts=" << output.counts << "AAAA" << std::endl;

  //Get sparse_score
  it++;
  if (it == util::TokenIter<util::MultiCharacter>::end()) return output;
  output.sparse_score = Trim(*it);
  //std::cerr << "output.sparse_score=" << output.sparse_score << "AAAA" << std::endl;

  //Get property
  it++;
  if (it == util::TokenIter<util::MultiCharacter>::end()) return output;
  output.property = Trim(*it);
  //std::cerr << "output.property=" << output.property << "AAAA" << std::endl;

  return output;
}

std::vector<unsigned char> splitWordAll1(const StringPiece &textin)
{
  const char delim[] = " ";
  const char delim2[] = "-";
  std::vector<unsigned char> output;

  //Split on space
  util::TokenIter<util::MultiCharacter> it(textin, util::MultiCharacter(delim));

  //For each int
  while (it) {
    //Split on dash (-)
    util::TokenIter<util::MultiCharacter> itInner(*it, util::MultiCharacter(delim2));

    //Insert the two entries in the vector. User will read entry 0 and 1 to get the first,
    //2 and 3 for second etc. Use unsigned char instead of int to save space, as
    //word allignments are all very small numbers that fit in a single byte
    output.push_back((unsigned char)(atoi(itInner->data())));
    itInner++;
    output.push_back((unsigned char)(atoi(itInner->data())));
    it++;
  }

  return output;

}

}

<commit_msg>synchronise with old cold<commit_after>#include "line_splitter.hh"

namespace Moses2
{

line_text splitLine(const StringPiece &textin)
{
  const char delim[] = "|||";
  line_text output;

  //Tokenize
  util::TokenIter<util::MultiCharacter> it(textin, util::MultiCharacter(delim));
  //Get source phrase
  output.source_phrase = Trim(*it);
  //std::cerr << "output.source_phrase=" << output.source_phrase << "AAAA" << std::endl;

  //Get target_phrase
  it++;
  output.target_phrase = Trim(*it);
  //std::cerr << "output.target_phrase=" << output.target_phrase << "AAAA" << std::endl;

  //Get probabilities
  it++;
  output.prob = Trim(*it);
  //std::cerr << "output.prob=" << output.prob << "AAAA" << std::endl;

  //Get WordAllignment
  it++;
  if (it == util::TokenIter<util::MultiCharacter>::end()) return output;
  output.word_align = Trim(*it);
  //std::cerr << "output.word_align=" << output.word_align << "AAAA" << std::endl;

  //Get count
  it++;
  if (it == util::TokenIter<util::MultiCharacter>::end()) return output;
  output.counts = Trim(*it);
  //std::cerr << "output.counts=" << output.counts << "AAAA" << std::endl;

  //Get sparse_score
  it++;
  if (it == util::TokenIter<util::MultiCharacter>::end()) return output;
  output.sparse_score = Trim(*it);
  //std::cerr << "output.sparse_score=" << output.sparse_score << "AAAA" << std::endl;

  //Get property
  it++;
  if (it == util::TokenIter<util::MultiCharacter>::end()) return output;
  output.property = Trim(*it);
  //std::cerr << "output.property=" << output.property << "AAAA" << std::endl;

  return output;
}

std::vector<unsigned char> splitWordAll1(const StringPiece &textin)
{
  const char delim[] = " ";
  const char delim2[] = "-";
  std::vector<unsigned char> output;

  //Case with no word alignments.
  if (textin.size() == 0) {
	return output;
  }

  //Split on space
  util::TokenIter<util::MultiCharacter> it(textin, util::MultiCharacter(delim));

  //For each int
  while (it) {
	//Split on dash (-)
	util::TokenIter<util::MultiCharacter> itInner(*it, util::MultiCharacter(delim2));

	//Insert the two entries in the vector. User will read entry 0 and 1 to get the first,
	//2 and 3 for second etc. Use unsigned char instead of int to save space, as
	//word allignments are all very small numbers that fit in a single byte
	output.push_back((unsigned char)(atoi(itInner->data())));
	itInner++;
	output.push_back((unsigned char)(atoi(itInner->data())));
	it++;
  }

  return output;

}

}

<|endoftext|>