<commit_before>#ifndef MJOLNIR_READ_LOCAL_INTERACTION_HPP
#define MJOLNIR_READ_LOCAL_INTERACTION_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/interaction/BondLengthInteraction.hpp>
#include <mjolnir/interaction/BondAngleInteraction.hpp>
#include <mjolnir/interaction/DihedralAngleInteraction.hpp>
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/throw_exception.hpp>
#include <mjolnir/util/logger.hpp>
#include <mjolnir/input/read_local_potential.hpp>
#include <memory>

namespace mjolnir
{

// ----------------------------------------------------------------------------
// individual local interaction. would be called from read_local_interaction
// defined at the bottom of this file.
// ----------------------------------------------------------------------------

template<typename traitsT>
std::unique_ptr<LocalInteractionBase<traitsT>>
read_bond_length_interaction(const std::string& kind, const toml::value& local)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_bond_length_interaction(), 0);
    using real_type = typename traitsT::real_type;

    const auto potential = toml::find<std::string>(local, "potential");
    if(potential == "Harmonic")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Harmonic.");
        using potentialT = HarmonicPotential<real_type>;

        return make_unique<BondLengthInteraction<traitsT, potentialT>>(
                kind, read_local_potential<2, potentialT>(local));
    }
    else if(potential == "Go1012Contact")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is 10-12 Go contact.");
        using potentialT = Go1012ContactPotential<real_type>;

        return make_unique<BondLengthInteraction<traitsT, potentialT>>(
                kind, read_local_potential<2, potentialT>(local));
    }
    else if(potential == "Gaussian")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Gaussian.");
        using potentialT = GaussianPotential<real_type>;

        return make_unique<BondLengthInteraction<traitsT, potentialT>>(
                kind, read_local_potential<2, potentialT>(local));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_bond_length_interaction: invalid potential",
            toml::find<toml::value>(local, "potential"), "here", {
            "expected value is one of the following.",
            "- \"Harmonic\"     : well-known harmonic potential",
            "- \"Go1012Contact\": r^12 - r^10 type native contact potential",
            "- \"Gaussian\"     : well-known gaussian potential"
            }));
    }
}

template<typename traitsT>
std::unique_ptr<LocalInteractionBase<traitsT>>
read_bond_angle_interaction(
    const typename LocalInteractionBase<traitsT>::connection_kind_type kind,
    const toml::value& local)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_bond_angle_interaction(), 0);
    using real_type = typename traitsT::real_type;

    const auto potential = toml::find<std::string>(local, "potential");

    if(potential == "Harmonic")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Harmonic.");
        using potentialT = HarmonicPotential<real_type>;

        return make_unique<BondAngleInteraction<traitsT, potentialT>>(
                kind, read_local_potential<3, potentialT>(local));
    }
    else if(potential == "FlexibleLocalAngle")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Flexible Local Angle.");
        using potentialT = FlexibleLocalAnglePotential<real_type>;

        return make_unique<BondAngleInteraction<traitsT, potentialT>>(
                kind, read_local_potential<3, potentialT>(local));
    }
    else if(potential == "Gaussian")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Gaussian.");
        using potentialT = GaussianPotential<real_type>;

        return make_unique<BondAngleInteraction<traitsT, potentialT>>(
                kind, read_local_potential<3, potentialT>(local));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_bond_angle_interaction: invalid potential",
            toml::find<toml::value>(local, "potential"), "here", {
            "expected value is one of the following.",
            "- \"Harmonic\"          : well-known harmonic potential",
            "- \"Gaussian\"          : well-known gaussian potential"
            "- \"FlexibleLocalAngle\": table-based potential for C-alpha protein model",
            }));
    }
}

template<typename traitsT>
std::unique_ptr<LocalInteractionBase<traitsT>>
read_dihedral_angle_interaction(
    const typename LocalInteractionBase<traitsT>::connection_kind_type kind,
    const toml::value& local)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_dihedral_angle_interaction(), 0);
    using real_type = typename traitsT::real_type;

    const auto potential = toml::find<std::string>(local, "potential");

    if(potential == "Harmonic")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Harmonic.");
        using potentialT = HarmonicPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    else if(potential == "ClementiDihedral")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Clementi-Go's dihedral.");
        using potentialT = ClementiDihedralPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    else if(potential == "Gaussian")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Gaussian.");
        using potentialT = GaussianPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    else if(potential == "PeriodicGaussian")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is PeriodicGaussian.");
        using potentialT = PeriodicGaussianPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    else if(potential == "FlexibleLocalDihedral")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Flexible Local Dihedral.");
        using potentialT = FlexibleLocalDihedralPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    // XXX generalization of this feature is too difficult (technically it's
    //     not so difficult, but practically, it makes the code messy...).
    else if(potential == "Gaussian+FlexibleLocalDihedral")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Gaussian + FlexibleLocalDihedral.");
        using potential_1_T = GaussianPotential<real_type>;
        using potential_2_T = FlexibleLocalDihedralPotential<real_type>;
        using potentialT    =
            SumLocalPotential<real_type, potential_1_T, potential_2_T>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(kind,
            read_local_potentials<4, real_type, potential_1_T, potential_2_T>(
                local, "Gaussian", "FlexibleLocalDihedral"));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_dihedral_angle_interaction: invalid potential",
            toml::find<toml::value>(local, "potential"), "here", {
            "expected value is one of the following.",
            "- \"Harmonic\"             : well-known harmonic potential",
            "- \"Gaussian\"             : well-known gaussian potential"
            "- \"ClementiDihedral\"     : potential used in the off-lattice Go protein model"
            "- \"FlexibleLocalDihedral\": table-based potential for C-alpha protein model",
            }));
    }
}

// ----------------------------------------------------------------------------
// general read_local_interaction function
// ----------------------------------------------------------------------------

template<typename traitsT>
std::unique_ptr<LocalInteractionBase<traitsT>>
read_local_interaction(const toml::value& local)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_local_interaction(), 0);

    const auto interaction = toml::find<std::string>(local, "interaction");
    const auto kind        = toml::find<std::string>(local, "topology");
    MJOLNIR_LOG_INFO("connection kind = ", kind);

    if(interaction == "BondLength")
    {
        MJOLNIR_LOG_NOTICE("Bond Length interaction found.");
        return read_bond_length_interaction<traitsT>(kind, local);
    }
    else if(interaction == "BondAngle")
    {
        MJOLNIR_LOG_NOTICE("Bond Angle interaction found.");
        return read_bond_angle_interaction<traitsT>(kind, local);
    }
    else if(interaction == "DihedralAngle")
    {
        MJOLNIR_LOG_NOTICE("Dihedral Angle interaction found.");
        return read_dihedral_angle_interaction<traitsT>(kind, local);
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_local_interaction: invalid interaction",
            toml::find<toml::value>(local, "interaction"), "here", {
            "expected value is one of the following.",
            "- \"BondLength\"    : 2-body well-known chemical bond interaction",
            "- \"BondAngle\"     : 3-body well-known bond angle interaction",
            "- \"DihedralAngle\" : 4-body well-known dihedral angle interaction",
            }));
    }
}

} // mjolnir
#endif// MJOLNIR_READ_LOCAL_INTERACTION
<commit_msg>fix reading SumLocalPotential<commit_after>#ifndef MJOLNIR_READ_LOCAL_INTERACTION_HPP
#define MJOLNIR_READ_LOCAL_INTERACTION_HPP
#include <extlib/toml/toml.hpp>
#include <mjolnir/interaction/BondLengthInteraction.hpp>
#include <mjolnir/interaction/BondAngleInteraction.hpp>
#include <mjolnir/interaction/DihedralAngleInteraction.hpp>
#include <mjolnir/util/make_unique.hpp>
#include <mjolnir/util/throw_exception.hpp>
#include <mjolnir/util/logger.hpp>
#include <mjolnir/input/read_local_potential.hpp>
#include <memory>

namespace mjolnir
{

// ----------------------------------------------------------------------------
// individual local interaction. would be called from read_local_interaction
// defined at the bottom of this file.
// ----------------------------------------------------------------------------

template<typename traitsT>
std::unique_ptr<LocalInteractionBase<traitsT>>
read_bond_length_interaction(const std::string& kind, const toml::value& local)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_bond_length_interaction(), 0);
    using real_type = typename traitsT::real_type;

    const auto potential = toml::find<std::string>(local, "potential");
    if(potential == "Harmonic")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Harmonic.");
        using potentialT = HarmonicPotential<real_type>;

        return make_unique<BondLengthInteraction<traitsT, potentialT>>(
                kind, read_local_potential<2, potentialT>(local));
    }
    else if(potential == "Go1012Contact")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is 10-12 Go contact.");
        using potentialT = Go1012ContactPotential<real_type>;

        return make_unique<BondLengthInteraction<traitsT, potentialT>>(
                kind, read_local_potential<2, potentialT>(local));
    }
    else if(potential == "Gaussian")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Gaussian.");
        using potentialT = GaussianPotential<real_type>;

        return make_unique<BondLengthInteraction<traitsT, potentialT>>(
                kind, read_local_potential<2, potentialT>(local));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_bond_length_interaction: invalid potential",
            toml::find<toml::value>(local, "potential"), "here", {
            "expected value is one of the following.",
            "- \"Harmonic\"     : well-known harmonic potential",
            "- \"Go1012Contact\": r^12 - r^10 type native contact potential",
            "- \"Gaussian\"     : well-known gaussian potential"
            }));
    }
}

template<typename traitsT>
std::unique_ptr<LocalInteractionBase<traitsT>>
read_bond_angle_interaction(
    const typename LocalInteractionBase<traitsT>::connection_kind_type kind,
    const toml::value& local)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_bond_angle_interaction(), 0);
    using real_type = typename traitsT::real_type;

    const auto potential = toml::find<std::string>(local, "potential");

    if(potential == "Harmonic")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Harmonic.");
        using potentialT = HarmonicPotential<real_type>;

        return make_unique<BondAngleInteraction<traitsT, potentialT>>(
                kind, read_local_potential<3, potentialT>(local));
    }
    else if(potential == "FlexibleLocalAngle")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Flexible Local Angle.");
        using potentialT = FlexibleLocalAnglePotential<real_type>;

        return make_unique<BondAngleInteraction<traitsT, potentialT>>(
                kind, read_local_potential<3, potentialT>(local));
    }
    else if(potential == "Gaussian")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Gaussian.");
        using potentialT = GaussianPotential<real_type>;

        return make_unique<BondAngleInteraction<traitsT, potentialT>>(
                kind, read_local_potential<3, potentialT>(local));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_bond_angle_interaction: invalid potential",
            toml::find<toml::value>(local, "potential"), "here", {
            "expected value is one of the following.",
            "- \"Harmonic\"          : well-known harmonic potential",
            "- \"Gaussian\"          : well-known gaussian potential"
            "- \"FlexibleLocalAngle\": table-based potential for C-alpha protein model",
            }));
    }
}

template<typename traitsT>
std::unique_ptr<LocalInteractionBase<traitsT>>
read_dihedral_angle_interaction(
    const typename LocalInteractionBase<traitsT>::connection_kind_type kind,
    const toml::value& local)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_dihedral_angle_interaction(), 0);
    using real_type = typename traitsT::real_type;

    const auto potential = toml::find<std::string>(local, "potential");

    if(potential == "Harmonic")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Harmonic.");
        using potentialT = HarmonicPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    else if(potential == "ClementiDihedral")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Clementi-Go's dihedral.");
        using potentialT = ClementiDihedralPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    else if(potential == "Gaussian")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Gaussian.");
        using potentialT = GaussianPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    else if(potential == "PeriodicGaussian")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is PeriodicGaussian.");
        using potentialT = PeriodicGaussianPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    else if(potential == "FlexibleLocalDihedral")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is Flexible Local Dihedral.");
        using potentialT = FlexibleLocalDihedralPotential<real_type>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(
            kind, read_local_potential<4, potentialT>(local));
    }
    // XXX generalization of this feature is too difficult (technically it's
    //     not so difficult, but practically, it makes the code messy...).
    else if(potential == "PeriodicGaussian+FlexibleLocalDihedral")
    {
        MJOLNIR_LOG_NOTICE("-- potential function is "
                           "PeriodicGaussian + FlexibleLocalDihedral.");
        using potential_1_T = PeriodicGaussianPotential<real_type>;
        using potential_2_T = FlexibleLocalDihedralPotential<real_type>;
        using potentialT    =
            SumLocalPotential<real_type, potential_1_T, potential_2_T>;

        return make_unique<DihedralAngleInteraction<traitsT, potentialT>>(kind,
            read_local_potentials<4, real_type, potential_1_T, potential_2_T>(
                local, "PeriodicGaussian", "FlexibleLocalDihedral"));
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_dihedral_angle_interaction: invalid potential",
            toml::find<toml::value>(local, "potential"), "here", {
            "expected value is one of the following.",
            "- \"Harmonic\"             : well-known harmonic potential",
            "- \"Gaussian\"             : well-known gaussian potential"
            "- \"ClementiDihedral\"     : potential used in the off-lattice Go protein model"
            "- \"FlexibleLocalDihedral\": table-based potential for C-alpha protein model",
            }));
    }
}

// ----------------------------------------------------------------------------
// general read_local_interaction function
// ----------------------------------------------------------------------------

template<typename traitsT>
std::unique_ptr<LocalInteractionBase<traitsT>>
read_local_interaction(const toml::value& local)
{
    MJOLNIR_GET_DEFAULT_LOGGER();
    MJOLNIR_SCOPE(read_local_interaction(), 0);

    const auto interaction = toml::find<std::string>(local, "interaction");
    const auto kind        = toml::find<std::string>(local, "topology");
    MJOLNIR_LOG_INFO("connection kind = ", kind);

    if(interaction == "BondLength")
    {
        MJOLNIR_LOG_NOTICE("Bond Length interaction found.");
        return read_bond_length_interaction<traitsT>(kind, local);
    }
    else if(interaction == "BondAngle")
    {
        MJOLNIR_LOG_NOTICE("Bond Angle interaction found.");
        return read_bond_angle_interaction<traitsT>(kind, local);
    }
    else if(interaction == "DihedralAngle")
    {
        MJOLNIR_LOG_NOTICE("Dihedral Angle interaction found.");
        return read_dihedral_angle_interaction<traitsT>(kind, local);
    }
    else
    {
        throw_exception<std::runtime_error>(toml::format_error("[error] "
            "mjolnir::read_local_interaction: invalid interaction",
            toml::find<toml::value>(local, "interaction"), "here", {
            "expected value is one of the following.",
            "- \"BondLength\"    : 2-body well-known chemical bond interaction",
            "- \"BondAngle\"     : 3-body well-known bond angle interaction",
            "- \"DihedralAngle\" : 4-body well-known dihedral angle interaction",
            }));
    }
}

} // mjolnir
#endif// MJOLNIR_READ_LOCAL_INTERACTION
<|endoftext|>


<commit_before>#include <sirius.h>

using namespace sirius;

void test_xc()
{
    XC_functional Ex("XC_LDA_X", 2);
    XC_functional Ec("XC_LDA_C_VWN", 2);

    int npt = 5;
    double rho_up[] = {0, 0.1, 0.2, 0.5, 2.234};
    double rho_dn[] = {0, 0.0, 0.1, 1.5, 2.234};

    std::vector<double> vx_up(npt);
    std::vector<double> vx_dn(npt);
    std::vector<double> vc_up(npt);
    std::vector<double> vc_dn(npt);
    std::vector<double> ex(npt);
    std::vector<double> ec(npt);

    /* compute XC potential and energy */
    Ex.get_lda(npt, rho_up, rho_dn, &vx_up[0], &vx_dn[0], &ex[0]);
    Ec.get_lda(npt, rho_up, rho_dn, &vc_up[0], &vc_dn[0], &ec[0]);
    for (int i = 0; i < npt; i++)
    {
        printf("%12.6f %12.6f %12.6f %12.6f %12.6f\n", rho_up[i], rho_dn[i], vx_up[i] + vc_up[i], vx_dn[i] + vc_dn[i], ex[i] + ec[i]);

    }
}

int main(int argn, char** argv)
{
    sirius::initialize(1);
    test_xc();
    sirius::finalize();
}
<commit_msg>update xc test<commit_after>#include <sirius.h>

using namespace sirius;

void test_xc()
{
    XC_functional Ex("XC_LDA_X", 2);
    XC_functional Ec("XC_LDA_C_VWN", 2);

    int npt = 5;
    double rho_up[] = {0, 0.1, 0.2, 0.5, 2.234};
    double rho_dn[] = {0, 0.0, 0.1, 1.5, 2.234};

    std::vector<double> vx_up(npt);
    std::vector<double> vx_dn(npt);
    std::vector<double> vc_up(npt);
    std::vector<double> vc_dn(npt);
    std::vector<double> ex(npt);
    std::vector<double> ec(npt);

    /* compute XC potential and energy */
    Ex.get_lda(npt, rho_up, rho_dn, &vx_up[0], &vx_dn[0], &ex[0]);
    Ec.get_lda(npt, rho_up, rho_dn, &vc_up[0], &vc_dn[0], &ec[0]);
    for (int i = 0; i < npt; i++)
    {
        printf("%12.6f %12.6f %12.6f %12.6f %12.6f\n", rho_up[i], rho_dn[i], vx_up[i] + vc_up[i], vx_dn[i] + vc_dn[i], ex[i] + ec[i]);

    }
}

void test_xc2()
{
    //XC_functional Ex("XC_GGA_X_PBE", 1);
    //XC_functional Ec("XC_GGA_C_PBE", 1);
    //XC_functional Ex("XC_LDA_X", 1);
    //XC_functional Ec("XC_LDA_C_PZ", 1);
    XC_functional Ex("XC_GGA_X_PW91", 1);
    XC_functional Ec("XC_GGA_C_PW91", 1);

    std::vector<double> sigma(101);
    std::vector<double> vrho(101);
    std::vector<double> vsigma(101);
    std::vector<double> e(101);

    auto fout = fopen("xc_libxc.dat", "w+");
    for (int i = 0; i <= 50; i++) {
        std::vector<double> rho(101, i * 0.2);
        for (int j = 0; j <= 100; j++) {
            sigma[j] = j * 0.1;
        }
        std::vector<double> result(101, 0);
        Ex.get_gga(101, rho.data(), sigma.data(), vrho.data(), vsigma.data(), e.data());
        //Ex.get_lda(101, rho.data(), vrho.data(), e.data());
        for (int i = 0; i <= 100; i++) {
            result[i] += e[i];
        }
        Ec.get_gga(101, rho.data(), sigma.data(), vrho.data(), vsigma.data(), e.data());
        //Ec.get_lda(101, rho.data(), vrho.data(), e.data());
        for (int i = 0; i <= 100; i++) {
            result[i] += e[i];
        }
        for (int i = 0; i <= 100; i++) {
            fprintf(fout, "%18.10f", result[i]);
        }
        fprintf(fout, "\n");
    }
    fclose(fout);
}

int main(int argn, char** argv)
{
    sirius::initialize(1);
    test_xc();
    test_xc2();
    sirius::finalize();
}
<|endoftext|>


<commit_before>/*#include <catch.hpp>

#include <pddlparse/AST.h>
#include <pddlparse/Parse.h>

////////////////////////////////////////////////////////////////////////////////////////////////////

TEST_CASE("[parser] The Blocksworld domain is parsed correctly", "[parser]")
{
	const pddl::Context::WarningCallback ignoreWarnings = [](const auto &, const auto &){};

	pddl::Tokenizer tokenizer;
	tokenizer.read("data/blocksworld-domain.pddl");
	pddl::Context context(std::move(tokenizer), ignoreWarnings);

	const auto description = pddl::parseDescription(context);

	REQUIRE_NOTHROW(description.domain());

	const auto &domain = description.domain();

	// Name
	CHECK(domain.name() == "blocks");

	// Requirements
	REQUIRE(domain.requirements().size() == 2u);
	CHECK(domain.requirements()[0].type() == Requirement::Type::STRIPS);
	CHECK(domain.requirements()[1].type() == Requirement::Type::Typing);

	// Types
	REQUIRE(domain.types().size() == 1u);

	const auto &block = *domain.types()[0];

	CHECK(block.name() == "block");
	REQUIRE(block.parentTypes().size() == 0u);

	// Predicates
	REQUIRE(domain.predicates().size() == 5u);

	const auto &on = *domain.predicates()[0];

	CHECK(on.name() == "on");
	REQUIRE(on.parameters().size() == 2u);
	CHECK(on.parameters()[0]->name() == "x");
	const auto &onArgument0Type = on.parameters()[0]->type()->as<expressions::PrimitiveType>();
	CHECK(&onArgument0Type == &block);
	CHECK(on.parameters()[1]->name() == "y");
	const auto &onArgument1Type = on.parameters()[1]->type()->as<expressions::PrimitiveType>();
	CHECK(&onArgument1Type == &block);

	const auto &handempty = *domain.predicates()[3];

	CHECK(handempty.name() == "handempty");
	CHECK(handempty.parameters().empty());

	// Actions
	REQUIRE(domain.actions().size() == 4u);

	const auto &pickUp = *domain.actions()[0];

	CHECK(pickUp.name() == "pick-up");
	REQUIRE(pickUp.parameters().size() == 1u);
	CHECK(pickUp.parameters()[0]->name() == "x");
	CHECK(pickUp.parameters()[0]->type() == &block);

	const auto &pickUpPre = pickUp.precondition()->as<expressions::And>();
	REQUIRE(pickUpPre.arguments().size() == 3u);
	const auto &pickUpPre0 = pickUpPre.arguments()[0]->as<expressions::Predicate>();
	CHECK(pickUpPre0.name() == "clear");
	REQUIRE(pickUpPre0.arguments().size() == 1u);
	const auto &pickUpPre00 = pickUpPre0.arguments()[0]->as<expressions::Variable>();
	CHECK(pickUpPre00.name() == "x");
	CHECK(pickUpPre00.type() == &block);
	CHECK(&pickUpPre00 == pickUp.parameters()[0].get());
	const auto &pickUpPre2 = pickUpPre.arguments()[2]->as<expressions::Predicate>();
	CHECK(pickUpPre2.name() == "handempty");
	CHECK(pickUpPre2.arguments().empty());

	const auto &pickUpEff = pickUp.effect()->as<expressions::And>();
	REQUIRE(pickUpEff.arguments().size() == 4u);
	const auto &pickUpEff0 = pickUpEff.arguments()[0]->as<expressions::Not>();
	const auto &pickUpEff00 = pickUpEff0.argument()->as<expressions::Predicate>();
	CHECK(pickUpEff00.name() == "ontable");
	REQUIRE(pickUpEff00.arguments().size() == 1u);
	const auto &pickUpEff000 = pickUpEff00.arguments()[0]->as<expressions::Variable>();
	CHECK(pickUpEff000.name() == "x");
	CHECK(pickUpEff000.type() == &block);
}
*/
<commit_msg>Removed unused test file.<commit_after><|endoftext|>


<commit_before>#include <QCoreApplication>
#include "GLApplicationController.h"

#include <typeinfo>
#include "GLPlatonicSolid.h"
#include "Sphere.h"
//#include "Cylinder.h"
//#include "Cone.h"
//#include "Torus.h"

GLApplicationController::GLApplicationController(GLWindow* window, Drawable* drawableObject)
	: window(window), drawable(drawableObject), animating(false)
{
	connect(window->canvasWidget, SIGNAL(changed()),
		this, SLOT(canvasWidgetChanged()));
	connect(window->actionQuit, SIGNAL(triggered()),
		QCoreApplication::instance(), SLOT(quit()));
	connect(window->xRotSlider, SIGNAL(valueChanged(int)),
		this, SLOT(xRotSliderChanged(int)));
	connect(window->yRotSlider, SIGNAL(valueChanged(int)),
		this, SLOT(yRotSliderChanged(int)));
	connect(window->zRotSlider, SIGNAL(valueChanged(int)),
		this, SLOT(zRotSliderChanged(int)));
	connect(window->animationCheckBox, SIGNAL(stateChanged(int)),
		this, SLOT(animationCheckBoxChanged(int)));

	connect(window->objectChooser, SIGNAL(currentIndexChanged(int)),
		this, SLOT(objectChooserIndexChanged(int)));
	connect(window->colourChooser, SIGNAL(currentIndexChanged(int)),
		this, SLOT(colourChooserIndexChanged(int)));

	animationTimer = new QTimer(this);
	connect(animationTimer, SIGNAL(timeout()), this, SLOT(nextAnimationFrame()));
	animationTimer->start(ANIMATION_FRAME_LENGTH);
}

void GLApplicationController::canvasWidgetChanged()
{
	window->resetInterface();
}

void GLApplicationController::xRotSliderChanged(int newValue)
{
	drawable->setXRotation( static_cast<float>(newValue) );
	window->resetInterface();
}

void GLApplicationController::yRotSliderChanged(int newValue)
{
	drawable->setYRotation( static_cast<float>(newValue) );
	window->resetInterface();
}

void GLApplicationController::zRotSliderChanged(int newValue)
{
	drawable->setZRotation( static_cast<float>(newValue) );
	window->resetInterface();
}

void GLApplicationController::animationCheckBoxChanged(int newState)
{
	animating = (newState == Qt::Checked);
}

void GLApplicationController::objectChooserIndexChanged(int newIndex)
{
	// We keep the drawable's current rendering method so
	// we can restore if it a new drawable is created
	RenderMethod oldRenderMethod = drawable->renderMethod();

	switch (newIndex)
	{
	case 0: // Sphere
		drawable = new Sphere(0.25, 10, 10);
		break;
	case 1: // Cylinder
		//drawable = new Cylinder();
		break;
	case 2: // Cone
		//drawable = new Cone();
		break;
	case 3: // Torus
		//drawable = new Torus();
		break;
	default: // if default case, just do nothing and leave current object
		return;
	}
	// Restore old render method and colouring
	drawable->setRenderMethod(oldRenderMethod);

	window->setDrawable(drawable);
	window->resetInterface();
}

void GLApplicationController::colourChooserIndexChanged(int newIndex)
{
	// TODO

	window->resetInterface();
}

void GLApplicationController::nextAnimationFrame()
{
	if (!animating) return;

	Vector3 rotation = drawable->rotation();
	if (rotation.x < 0.0f || rotation.x > 360.0f) rotation.x = 0.0f;
	else rotation.x += 1.0f;
	if (rotation.y < 0.0f || rotation.y > 360.0f) rotation.y = 0.0f;
	else rotation.y += 1.0f;
	if (rotation.z < 0.0f || rotation.z > 360.0f) rotation.z = 0.0f;
	else rotation.z += 1.0f;
	drawable->setRotation(rotation);

	window->resetInterface();
}
<commit_msg>Combo box for colouring now changes the colouring<commit_after>#include <QCoreApplication>
#include "GLApplicationController.h"

#include <typeinfo>
#include "GLPlatonicSolid.h"
#include "Sphere.h"
//#include "Cylinder.h"
//#include "Cone.h"
//#include "Torus.h"

GLApplicationController::GLApplicationController(GLWindow* window, Drawable* drawableObject)
	: window(window), drawable(drawableObject), animating(false)
{
	connect(window->canvasWidget, SIGNAL(changed()),
		this, SLOT(canvasWidgetChanged()));
	connect(window->actionQuit, SIGNAL(triggered()),
		QCoreApplication::instance(), SLOT(quit()));
	connect(window->xRotSlider, SIGNAL(valueChanged(int)),
		this, SLOT(xRotSliderChanged(int)));
	connect(window->yRotSlider, SIGNAL(valueChanged(int)),
		this, SLOT(yRotSliderChanged(int)));
	connect(window->zRotSlider, SIGNAL(valueChanged(int)),
		this, SLOT(zRotSliderChanged(int)));
	connect(window->animationCheckBox, SIGNAL(stateChanged(int)),
		this, SLOT(animationCheckBoxChanged(int)));

	connect(window->objectChooser, SIGNAL(currentIndexChanged(int)),
		this, SLOT(objectChooserIndexChanged(int)));
	connect(window->colourChooser, SIGNAL(currentIndexChanged(int)),
		this, SLOT(colourChooserIndexChanged(int)));

	animationTimer = new QTimer(this);
	connect(animationTimer, SIGNAL(timeout()), this, SLOT(nextAnimationFrame()));
	animationTimer->start(ANIMATION_FRAME_LENGTH);
}

void GLApplicationController::canvasWidgetChanged()
{
	window->resetInterface();
}

void GLApplicationController::xRotSliderChanged(int newValue)
{
	drawable->setXRotation( static_cast<float>(newValue) );
	window->resetInterface();
}

void GLApplicationController::yRotSliderChanged(int newValue)
{
	drawable->setYRotation( static_cast<float>(newValue) );
	window->resetInterface();
}

void GLApplicationController::zRotSliderChanged(int newValue)
{
	drawable->setZRotation( static_cast<float>(newValue) );
	window->resetInterface();
}

void GLApplicationController::animationCheckBoxChanged(int newState)
{
	animating = (newState == Qt::Checked);
}

void GLApplicationController::objectChooserIndexChanged(int newIndex)
{
	// We keep the drawable's current rendering method so
	// we can restore if it a new drawable is created
	RenderMethod oldRenderMethod = drawable->renderMethod();

	switch (newIndex)
	{
	case 0: // Sphere
		drawable = new Sphere(0.25, 10, 10);
		break;
	case 1: // Cylinder
		//drawable = new Cylinder();
		break;
	case 2: // Cone
		//drawable = new Cone();
		break;
	case 3: // Torus
		//drawable = new Torus();
		break;
	default: // if default case, just do nothing and leave current object
		return;
	}
	// Restore old render method and colouring (if instance is a mesh)
	drawable->setRenderMethod(oldRenderMethod);
	Mesh* meshObject = dynamic_cast<Mesh*>(drawable);
	if (meshObject)
		meshObject->setColouring( static_cast<Mesh::Colouring>(newIndex) );

	window->setDrawable(drawable);
	window->resetInterface();
}

void GLApplicationController::colourChooserIndexChanged(int newIndex)
{
	// If object is an instance of mesh, assign new colouring
	Mesh* meshObject = dynamic_cast<Mesh*>(drawable);
	if (meshObject)
		meshObject->setColouring( static_cast<Mesh::Colouring>(newIndex) );

	window->resetInterface();
}

void GLApplicationController::nextAnimationFrame()
{
	if (!animating) return;

	Vector3 rotation = drawable->rotation();
	if (rotation.x < 0.0f || rotation.x > 360.0f) rotation.x = 0.0f;
	else rotation.x += 1.0f;
	if (rotation.y < 0.0f || rotation.y > 360.0f) rotation.y = 0.0f;
	else rotation.y += 1.0f;
	if (rotation.z < 0.0f || rotation.z > 360.0f) rotation.z = 0.0f;
	else rotation.z += 1.0f;
	drawable->setRotation(rotation);

	window->resetInterface();
}
<|endoftext|>


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

#include "ChunkedIstream.hxx"
#include "FacadeIstream.hxx"
#include "Bucket.hxx"
#include "New.hxx"
#include "UnusedPtr.hxx"
#include "util/ConstBuffer.hxx"
#include "util/DestructObserver.hxx"
#include "util/HexFormat.hxx"
#include "util/SpanCast.hxx"

#include <algorithm>

#include <assert.h>
#include <string.h>

using std::string_view_literals::operator""sv;

class ChunkedIstream final : public FacadeIstream, DestructAnchor {
	/**
	 * This flag is true while writing the buffer inside _Read().
	 * OnData() will check it, and refuse to accept more data from the
	 * input.  This avoids writing the buffer recursively.
	 */
	bool writing_buffer = false;

	char buffer[7];
	size_t buffer_sent = sizeof(buffer);

	size_t missing_from_current_chunk = 0;

public:
	ChunkedIstream(struct pool &p, UnusedIstreamPtr &&_input) noexcept
		:FacadeIstream(p, std::move(_input)) {}

	/* virtual methods from class Istream */

	void _Read() noexcept override;
	void _FillBucketList(IstreamBucketList &list) override;
	size_t _ConsumeBucketList(size_t nbytes) noexcept override;

	/* virtual methods from class IstreamHandler */

	bool OnIstreamReady() noexcept override {
		return InvokeReady();
	}

	size_t OnData(const void *data, size_t length) noexcept override;
	void OnEof() noexcept override;
	void OnError(std::exception_ptr ep) noexcept override;

private:
	bool IsBufferEmpty() const noexcept {
		assert(buffer_sent <= sizeof(buffer));

		return buffer_sent == sizeof(buffer);
	}

	/** set the buffer length and return a pointer to the first byte */
	char *SetBuffer(size_t length) noexcept {
		assert(IsBufferEmpty());
		assert(length <= sizeof(buffer));

		buffer_sent = sizeof(buffer) - length;
		return buffer + buffer_sent;
	}

	/** append data to the buffer */
	void AppendToBuffer(const void *data, size_t length) noexcept;

	void StartChunk(size_t length) noexcept;

	ConstBuffer<void> ReadBuffer() noexcept {
		return { buffer + buffer_sent, sizeof(buffer) - buffer_sent };
	}

	size_t ConsumeBuffer(size_t nbytes) noexcept {
		size_t size = ReadBuffer().size;
		if (size > nbytes)
			size = nbytes;

		if (size > 0) {
			buffer_sent += size;
			Consumed(size);
		}

		return size;
	}

	/**
	 * Returns true if the buffer is consumed.
	 */
	bool SendBuffer() noexcept;

	/**
	 * Wrapper for SendBuffer() that sets and clears the
	 * #writing_buffer flag.  This requires acquiring a pool reference
	 * to do that safely.
	 *
	 * @return true if the buffer is consumed.
	 */
	bool SendBuffer2() noexcept;

	size_t Feed(const char *data, size_t length) noexcept;
};

void
ChunkedIstream::AppendToBuffer(const void *data, size_t length) noexcept
{
	assert(data != nullptr);
	assert(length > 0);
	assert(length <= buffer_sent);

	const auto old = ReadBuffer();

#ifndef NDEBUG
	/* simulate a buffer reset; if we don't do this, an assertion in
	   SetBuffer() fails (which is invalid for this special case) */
	buffer_sent = sizeof(buffer);
#endif

	auto dest = SetBuffer(old.size + length);
	memmove(dest, old.data, old.size);
	dest += old.size;

	memcpy(dest, data, length);
}

void
ChunkedIstream::StartChunk(size_t length) noexcept
{
	assert(length > 0);
	assert(IsBufferEmpty());
	assert(missing_from_current_chunk == 0);

	if (length > 0x8000)
		/* maximum chunk size is 32kB for now */
		length = 0x8000;

	missing_from_current_chunk = length;

	char *p = SetBuffer(6);
	p = HexFormatUint16Fixed(p, (uint16_t)length);
	*p++ = '\r';
	*p++ = '\n';
}

bool
ChunkedIstream::SendBuffer() noexcept
{
	auto r = ReadBuffer();
	if (r.empty())
		return true;

	size_t nbytes = InvokeData(r.data, r.size);
	if (nbytes > 0)
		buffer_sent += nbytes;

	return nbytes == r.size;
}

bool
ChunkedIstream::SendBuffer2() noexcept
{
	const DestructObserver destructed(*this);

	assert(!writing_buffer);
	writing_buffer = true;

	const bool result = SendBuffer();
	if (!destructed)
		writing_buffer = false;
	return result;
}

inline size_t
ChunkedIstream::Feed(const char *data, size_t length) noexcept
{
	const DestructObserver destructed(*this);

	size_t total = 0, rest, nbytes;

	assert(input.IsDefined());

	do {
		assert(!writing_buffer);

		if (IsBufferEmpty() && missing_from_current_chunk == 0)
			StartChunk(length - total);

		if (!SendBuffer())
			return destructed ? 0 : total;

		assert(IsBufferEmpty());

		if (missing_from_current_chunk == 0) {
			/* we have just written the previous chunk trailer;
			   re-start this loop to start a new chunk */
			nbytes = rest = 0;
			continue;
		}

		rest = length - total;
		if (rest > missing_from_current_chunk)
			rest = missing_from_current_chunk;

		nbytes = InvokeData(data + total, rest);
		if (nbytes == 0)
			return destructed ? 0 : total;

		total += nbytes;

		missing_from_current_chunk -= nbytes;
		if (missing_from_current_chunk == 0) {
			/* a chunk ends with "\r\n" */
			char *p = SetBuffer(2);
			p[0] = '\r';
			p[1] = '\n';
		}
	} while ((!IsBufferEmpty() || total < length) && nbytes == rest);

	return total;
}

/*
 * istream handler
 *
 */

size_t
ChunkedIstream::OnData(const void *data, size_t length) noexcept
{
	if (writing_buffer)
		/* this is a recursive call from _Read(): bail out */
		return 0;

	return Feed((const char*)data, length);
}

void
ChunkedIstream::OnEof() noexcept
{
	assert(input.IsDefined());
	assert(missing_from_current_chunk == 0);

	input.Clear();

	/* write EOF chunk (length 0) */

	AppendToBuffer("0\r\n\r\n", 5);

	/* flush the buffer */

	if (SendBuffer())
		DestroyEof();
}

void
ChunkedIstream::OnError(std::exception_ptr ep) noexcept
{
	assert(input.IsDefined());

	input.Clear();
	DestroyError(ep);
}

/*
 * istream implementation
 *
 */

void
ChunkedIstream::_Read() noexcept
{
	if (!SendBuffer2())
		return;

	if (!input.IsDefined()) {
		DestroyEof();
		return;
	}

	if (IsBufferEmpty() && missing_from_current_chunk == 0) {
		off_t available = input.GetAvailable(true);
		if (available > 0) {
			StartChunk(available);
			if (!SendBuffer2())
				return;
		}
	}

	input.Read();
}

void
ChunkedIstream::_FillBucketList(IstreamBucketList &list)
{
	if (!input.IsDefined()) {
		// TODO: generate EOF chunk
		list.SetMore();
		return;
	}

	auto b = ReadBuffer();
	if (b.empty() && missing_from_current_chunk == 0) {
		off_t available = input.GetAvailable(true);
		if (available > 0) {
			StartChunk(available);
			b = ReadBuffer();
		}
	}

	if (!b.empty())
		list.Push(b);

	if (missing_from_current_chunk > 0) {
		assert(input.IsDefined());

		IstreamBucketList sub;
		try {
			input.FillBucketList(sub);
		} catch (...) {
			Destroy();
			throw;
		}

		size_t nbytes = list.SpliceBuffersFrom(std::move(sub),
						       missing_from_current_chunk);
		if (nbytes >= missing_from_current_chunk)
			list.Push(AsBytes("\r\n"sv));
	}

	list.SetMore();
}

size_t
ChunkedIstream::_ConsumeBucketList(size_t nbytes) noexcept
{
	size_t total = 0;

	size_t size = ConsumeBuffer(nbytes);
	nbytes -= size;
	total += size;

	size = std::min(nbytes, missing_from_current_chunk);
	if (size > 0) {
		assert(input.IsDefined());

		size = input.ConsumeBucketList(size);
		Consumed(size);
		nbytes -= size;
		total += size;

		missing_from_current_chunk -= size;
		if (missing_from_current_chunk == 0) {
			/* a chunk ends with "\r\n" */
			char *p = SetBuffer(2);
			p[0] = '\r';
			p[1] = '\n';

			size = ConsumeBuffer(nbytes);
			nbytes -= size;
			total += size;
		}

		if (nbytes > 0)
			/* if data still remains, then our input must
			   have reached end-of-file */
			CloseInput();
	}

	return total;
}

/*
 * constructor
 *
 */

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

#include "ChunkedIstream.hxx"
#include "FacadeIstream.hxx"
#include "Bucket.hxx"
#include "New.hxx"
#include "UnusedPtr.hxx"
#include "util/ConstBuffer.hxx"
#include "util/DestructObserver.hxx"
#include "util/HexFormat.hxx"
#include "util/SpanCast.hxx"

#include <algorithm>
#include <array>
#include <cassert>

#include <string.h>

using std::string_view_literals::operator""sv;

class ChunkedIstream final : public FacadeIstream, DestructAnchor {
	/**
	 * This flag is true while writing the buffer inside _Read().
	 * OnData() will check it, and refuse to accept more data from the
	 * input.  This avoids writing the buffer recursively.
	 */
	bool writing_buffer = false;

	std::array<char, 7> buffer;
	size_t buffer_sent = buffer.size();

	size_t missing_from_current_chunk = 0;

public:
	ChunkedIstream(struct pool &p, UnusedIstreamPtr &&_input) noexcept
		:FacadeIstream(p, std::move(_input)) {}

	/* virtual methods from class Istream */

	void _Read() noexcept override;
	void _FillBucketList(IstreamBucketList &list) override;
	size_t _ConsumeBucketList(size_t nbytes) noexcept override;

	/* virtual methods from class IstreamHandler */

	bool OnIstreamReady() noexcept override {
		return InvokeReady();
	}

	size_t OnData(const void *data, size_t length) noexcept override;
	void OnEof() noexcept override;
	void OnError(std::exception_ptr ep) noexcept override;

private:
	bool IsBufferEmpty() const noexcept {
		assert(buffer_sent <= buffer.size());

		return buffer_sent == buffer.size();
	}

	/** set the buffer length and return a pointer to the first byte */
	char *SetBuffer(size_t length) noexcept {
		assert(IsBufferEmpty());
		assert(length <= buffer.size());

		buffer_sent = buffer.size() - length;
		return buffer.data() + buffer_sent;
	}

	/** append data to the buffer */
	void AppendToBuffer(std::string_view src) noexcept;

	void StartChunk(size_t length) noexcept;

	std::span<const char> ReadBuffer() noexcept {
		return std::span{buffer}.subspan(buffer_sent);
	}

	size_t ConsumeBuffer(size_t nbytes) noexcept {
		size_t size = ReadBuffer().size();
		if (size > nbytes)
			size = nbytes;

		if (size > 0) {
			buffer_sent += size;
			Consumed(size);
		}

		return size;
	}

	/**
	 * Returns true if the buffer is consumed.
	 */
	bool SendBuffer() noexcept;

	/**
	 * Wrapper for SendBuffer() that sets and clears the
	 * #writing_buffer flag.  This requires acquiring a pool reference
	 * to do that safely.
	 *
	 * @return true if the buffer is consumed.
	 */
	bool SendBuffer2() noexcept;

	size_t Feed(const char *data, size_t length) noexcept;
};

void
ChunkedIstream::AppendToBuffer(std::string_view src) noexcept
{
	assert(!src.empty());
	assert(src.size() <= buffer_sent);

	const auto old = ReadBuffer();

#ifndef NDEBUG
	/* simulate a buffer reset; if we don't do this, an assertion in
	   SetBuffer() fails (which is invalid for this special case) */
	buffer_sent = buffer.size();
#endif

	auto dest = SetBuffer(old.size() + src.size());
	dest = std::copy(old.begin(), old.end(), dest);
	std::copy(src.begin(), src.end(), dest);
}

void
ChunkedIstream::StartChunk(size_t length) noexcept
{
	assert(length > 0);
	assert(IsBufferEmpty());
	assert(missing_from_current_chunk == 0);

	if (length > 0x8000)
		/* maximum chunk size is 32kB for now */
		length = 0x8000;

	missing_from_current_chunk = length;

	char *p = (char *)SetBuffer(6);
	p = HexFormatUint16Fixed(p, (uint16_t)length);
	*p++ = '\r';
	*p++ = '\n';
}

bool
ChunkedIstream::SendBuffer() noexcept
{
	auto r = ReadBuffer();
	if (r.empty())
		return true;

	size_t nbytes = InvokeData(r.data(), r.size());
	if (nbytes > 0)
		buffer_sent += nbytes;

	return nbytes == r.size();
}

bool
ChunkedIstream::SendBuffer2() noexcept
{
	const DestructObserver destructed(*this);

	assert(!writing_buffer);
	writing_buffer = true;

	const bool result = SendBuffer();
	if (!destructed)
		writing_buffer = false;
	return result;
}

inline size_t
ChunkedIstream::Feed(const char *data, size_t length) noexcept
{
	const DestructObserver destructed(*this);

	size_t total = 0, rest, nbytes;

	assert(input.IsDefined());

	do {
		assert(!writing_buffer);

		if (IsBufferEmpty() && missing_from_current_chunk == 0)
			StartChunk(length - total);

		if (!SendBuffer())
			return destructed ? 0 : total;

		assert(IsBufferEmpty());

		if (missing_from_current_chunk == 0) {
			/* we have just written the previous chunk trailer;
			   re-start this loop to start a new chunk */
			nbytes = rest = 0;
			continue;
		}

		rest = length - total;
		if (rest > missing_from_current_chunk)
			rest = missing_from_current_chunk;

		nbytes = InvokeData(data + total, rest);
		if (nbytes == 0)
			return destructed ? 0 : total;

		total += nbytes;

		missing_from_current_chunk -= nbytes;
		if (missing_from_current_chunk == 0) {
			/* a chunk ends with "\r\n" */
			char *p = SetBuffer(2);
			p[0] = '\r';
			p[1] = '\n';
		}
	} while ((!IsBufferEmpty() || total < length) && nbytes == rest);

	return total;
}

/*
 * istream handler
 *
 */

size_t
ChunkedIstream::OnData(const void *data, size_t length) noexcept
{
	if (writing_buffer)
		/* this is a recursive call from _Read(): bail out */
		return 0;

	return Feed((const char*)data, length);
}

void
ChunkedIstream::OnEof() noexcept
{
	assert(input.IsDefined());
	assert(missing_from_current_chunk == 0);

	input.Clear();

	/* write EOF chunk (length 0) */

	AppendToBuffer("0\r\n\r\n"sv);

	/* flush the buffer */

	if (SendBuffer())
		DestroyEof();
}

void
ChunkedIstream::OnError(std::exception_ptr ep) noexcept
{
	assert(input.IsDefined());

	input.Clear();
	DestroyError(ep);
}

/*
 * istream implementation
 *
 */

void
ChunkedIstream::_Read() noexcept
{
	if (!SendBuffer2())
		return;

	if (!input.IsDefined()) {
		DestroyEof();
		return;
	}

	if (IsBufferEmpty() && missing_from_current_chunk == 0) {
		off_t available = input.GetAvailable(true);
		if (available > 0) {
			StartChunk(available);
			if (!SendBuffer2())
				return;
		}
	}

	input.Read();
}

void
ChunkedIstream::_FillBucketList(IstreamBucketList &list)
{
	if (!input.IsDefined()) {
		// TODO: generate EOF chunk
		list.SetMore();
		return;
	}

	auto b = ReadBuffer();
	if (b.empty() && missing_from_current_chunk == 0) {
		off_t available = input.GetAvailable(true);
		if (available > 0) {
			StartChunk(available);
			b = ReadBuffer();
		}
	}

	if (!b.empty())
		list.Push(std::as_bytes(b));

	if (missing_from_current_chunk > 0) {
		assert(input.IsDefined());

		IstreamBucketList sub;
		try {
			input.FillBucketList(sub);
		} catch (...) {
			Destroy();
			throw;
		}

		size_t nbytes = list.SpliceBuffersFrom(std::move(sub),
						       missing_from_current_chunk);
		if (nbytes >= missing_from_current_chunk)
			list.Push(AsBytes("\r\n"sv));
	}

	list.SetMore();
}

size_t
ChunkedIstream::_ConsumeBucketList(size_t nbytes) noexcept
{
	size_t total = 0;

	size_t size = ConsumeBuffer(nbytes);
	nbytes -= size;
	total += size;

	size = std::min(nbytes, missing_from_current_chunk);
	if (size > 0) {
		assert(input.IsDefined());

		size = input.ConsumeBucketList(size);
		Consumed(size);
		nbytes -= size;
		total += size;

		missing_from_current_chunk -= size;
		if (missing_from_current_chunk == 0) {
			/* a chunk ends with "\r\n" */
			char *p = SetBuffer(2);
			p[0] = '\r';
			p[1] = '\n';

			size = ConsumeBuffer(nbytes);
			nbytes -= size;
			total += size;
		}

		if (nbytes > 0)
			/* if data still remains, then our input must
			   have reached end-of-file */
			CloseInput();
	}

	return total;
}

/*
 * constructor
 *
 */

UnusedIstreamPtr
istream_chunked_new(struct pool &pool, UnusedIstreamPtr input) noexcept
{
	return NewIstreamPtr<ChunkedIstream>(pool, std::move(input));
}
<|endoftext|>


<commit_before>/*
 * word.cpp
 */

#include "word.h"

Word::Word()
{
  value = "";
  frequency = 0;
}

Word::Word(std::string val)
{
  std::string text;
  std::remove_copy_if(val.begin(), val.end(), std::back_inserter(text),std::ptr_fun<int,int>(&std::ispunct));

  value = text;
  frequency = 1;
}

Word::~Word(){}

Word::Word(const Word& w)
{
  value = w.value;
  frequency = w.frequency;
}

std::string Word::getVal()
{
  return value;
}

int Word::getFrequency()
{
  return frequency;
}

void Word::setVal(std::string newValue)
{
  value = newValue;
}

void Word::setFrequency(int newFrequency)
{
  frequency = newFrequency;
}

void Word::incrementFrequency()
{
  frequency++;
}

bool Word::operator==(const Word& w)
{
  return (w.value == this->value);
}

std::ostream& operator<<(std::ostream& os, const Word& w)
{
  os<<w.value<<" | "<<w.frequency;
  return os;
}
<commit_msg>added to lower in word constructor & clean up<commit_after>/*
 * word.cpp
 */

#include "word.h"
#include <locale>

Word::Word()
{
  value = "";
  frequency = 0;
}

Word::Word(std::string val)
{
  std::string text;

  //remove punctuation
  std::remove_copy_if(val.begin(), val.end(), std::back_inserter(text),std::ptr_fun<int,int>(&std::ispunct));

  //to lower case
  std::locale loc;
  for (std::string::size_type i=0; i<text.length(); ++i) {
    text[i] = std::tolower(text[i],loc);
  }
  value = text;
  frequency = 1;
}

Word::~Word(){}

Word::Word(const Word& w)
{
  value = w.value;
  frequency = w.frequency;
}

std::string Word::getVal()
{
  return value;
}

int Word::getFrequency()
{
  return frequency;
}

void Word::setVal(std::string newValue)
{
  value = newValue;
}

void Word::setFrequency(int newFrequency)
{
  frequency = newFrequency;
}

void Word::incrementFrequency()
{
  frequency++;
}

bool Word::operator==(const Word& w)
{
  return (w.value == this->value);
}

std::ostream& operator<<(std::ostream& os, const Word& w)
{
  os<<w.value<<" | "<<w.frequency;
  return os;
}
<|endoftext|>


<commit_before>#include "AsyncServer.h"

// #include <jemalloc/jemalloc.h>
#include <macgyver/AsyncTaskGroup.h>
#include <macgyver/AnsiEscapeCodes.h>
#include <macgyver/Exception.h>
#include <spine/HTTP.h>
#include <spine/Options.h>
#include <spine/Reactor.h>
#include <spine/SmartMet.h>
#include <spine/Convenience.h>
#include <sys/types.h>
#include <sys/select.h>
#include <atomic>
#include <csignal>
#include <iostream>
#include <memory>
#include <new>
#include <thread>

// libdw from elfutils-devel provides more details than libbfd
#define BACKWARD_HAS_DW 1
#include "backward.h"

std::unique_ptr<SmartMet::Server::Server> server;
std::unique_ptr<SmartMet::Spine::Reactor> reactor;
std::unique_ptr<Fmi::AsyncTaskGroup> tasks;

std::atomic<int> last_signal(0);

// Allowed core dump signals. Note that we choose to ignore SIGBUS though due to
// NFS problems, and SIGQUIT since we want to allow quitting via keyboard

std::vector<int> core_signals{SIGILL, SIGABRT, SIGFPE, SIGSYS, SIGSEGV, SIGXCPU, SIGXFSZ};

void crash_signal_handler(int sig)
{
  std::cout << "---------------------------------------------------------\n";
  std::cout << SmartMet::Spine::log_time_str() << " THE SYSTEM IS GOING DOWN (signal=" << sig << ")\n";
  std::cout << "---------------------------------------------------------\n";
  auto requests = reactor->getActiveRequests();
  for (auto it = requests.begin(); it != requests.end(); ++it)
  {
    std::cout << it->second.request.getURI() << "\n";
    std::cout << "---------------------------------------------------------\n";
  }
  signal(sig, SIG_DFL);
  raise(sig);
}

void signal_handler(int sig)
{
  last_signal = sig;
}
// Block all signals except profiling
void block_signals()
{
  sigset_t signal_set;
  sigfillset(&signal_set);

  // Enable debugging
  sigdelset(&signal_set, SIGPROF);

  // Enable core dumps from fatal errors
  for (auto sig : core_signals)
    sigdelset(&signal_set, sig);

  pthread_sigmask(SIG_BLOCK, &signal_set, nullptr);
}

void set_new_handler(const std::string& name)
{
  if (name == "default")  // system default may change in C++20
    ;
  else if (name == "bad_alloc")
    std::set_new_handler([] { throw std::bad_alloc(); });
  else if (name == "terminate")
    std::set_new_handler([] { std::terminate(); });
  else
    throw Fmi::Exception(BCP, "Unknown new_handler").addParameter("name", name);
}

int main(int argc, char* argv[])
{
  try
  {
    // Parse options

    SmartMet::Spine::Options options;
    if (!options.parse(argc, argv))
      exit(1);

    // Use the system locale or autocomplete may not work properly (iconv requirement)
    std::setlocale(LC_ALL, "");

    // Set new_handler
    set_new_handler(options.new_handler);

    const auto signals_init =
        [] ()
        {
            // Block signals before starting new threads

            block_signals();

            // Set special SIGTERM, SIGBUS and SIGWINCH handlers

            struct sigaction action;             // NOLINT(cppcoreguidelines-pro-type-member-init)
            action.sa_handler = signal_handler;  // NOLINT(cppcoreguidelines-pro-type-union-access)
            sigemptyset(&action.sa_mask);
            action.sa_flags = 0;
            sigaction(SIGBUS, &action, nullptr);
            sigaction(SIGTERM, &action, nullptr);
            sigaction(SIGWINCH, &action, nullptr);

            // We also want to record other common non-core dumping signals
            sigaction(SIGHUP, &action, nullptr);
            sigaction(SIGINT, &action, nullptr);

            struct sigaction action2;             // NOLINT(cppcoreguidelines-pro-type-member-init)
            action2.sa_handler = crash_signal_handler;  // NOLINT(cppcoreguidelines-pro-type-union-access)
            sigemptyset(&action2.sa_mask);
            action2.sa_flags = 0;
            sigaction(SIGSEGV, &action2, nullptr);

        };

    std::unique_ptr<backward::SignalHandling> sh;
    if (options.stacktrace)
      sh.reset(new backward::SignalHandling(core_signals));

    reactor.reset(new SmartMet::Spine::Reactor(options));

    server.reset(new SmartMet::Server::AsyncServer(options, *reactor));

    tasks.reset(new Fmi::AsyncTaskGroup);
    tasks->on_task_error([] (const std::string&) { throw; });
    tasks->stop_on_error(true);

    tasks->add(
        "SmartMet::Spine::Reactor::init",
        [signals_init] ()
        {
            signals_init();
            reactor->init();
        });

    tasks->add(
        "Run SmartMet::Server::AsyncServer",
        [signals_init] ()
        {
            signals_init();
            std::this_thread::sleep_for(std::chrono::seconds(3));
            std::cout << ANSI_BG_GREEN << ANSI_BOLD_ON << ANSI_FG_WHITE << "Launched Synapse server"
                      << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT << std::endl;
            server->run();
        });

    // Sleep until a signal comes, and then either handle it or exit

    double sigint_cnt = 0;

    while (true)
    {
        struct timeval tv;
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        errno = 0;
        if (select(0, nullptr, nullptr, nullptr, &tv) >= 0) {
            tasks->handle_finished();
            // FIXME: handle case when all tasks have ended
        } else if (errno != EINTR) {
            std::cout << ANSI_BG_RED << ANSI_BOLD_ON << ANSI_FG_WHITE
                      << "Unexpected error code from select(): "
                      << strerror(errno)
                      << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                      << std::endl;
        }

        int sig = last_signal;
        if (sig != 0) {
            std::cout << "\n"
                      << ANSI_BG_RED << ANSI_BOLD_ON << ANSI_FG_WHITE << "Signal '"
                      << strsignal(sig) << "' (" << sig << ") received ";

            if (sig == SIGBUS || sig == SIGWINCH)
            {
                std::cout << " - ignoring it!"
                          << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                          << std::endl;
                last_signal = 0;
            }
            else if (sig == SIGTERM)
            {
                std::cout << " - shutting down!"
                          << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                          << std::endl;

                tasks->stop();
                server->shutdownServer();
                tasks->wait();

                // Save heap profile if it has been enabled
                // mallctl("prof.dump", nullptr, nullptr, nullptr, 0);
                return 0;
            }
            else if (sig == SIGINT)
            {
	        last_signal = 0;
                Fmi::AsyncTask shutdown_timer("Shutdown timer",
					      [&sigint_cnt]()
					      {
						  for (int i = 0; i < 1200; i++)
						  {
						      boost::this_thread::sleep_for(boost::chrono::milliseconds(50));
						      if (last_signal == SIGINT || last_signal == SIGTERM) {
							  last_signal = 0;
							  sigint_cnt++;
                                                          if (sigint_cnt > 5) {
							      std::cout << "*** Too many SIGINT or SIGTERM signals after first SIGINT. Commiting suicide" << std::endl;
							      abort();
							  }
						      } else {
							  sigint_cnt = std::max(0.0, sigint_cnt - 0.05);
						      }
						  }
						  std::cout << "*** Timed out waiting for server to shut down after SIGINT" << std::endl;
                                                  abort();
					      });
                std::cout << " - shutting down!"
                          << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                          << std::endl;

                tasks->stop();
                server->shutdownServer();
                tasks->wait();
		shutdown_timer.cancel();

                // Save heap profile if it has been enabled
                // mallctl("prof.dump", nullptr, nullptr, nullptr, 0);
                return 0;
            }
            else
            {
                std::cout << " - exiting!" << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                          << std::endl;
                break;
            }
        }
    }

    return 666;
  }
  catch (...)
  {
    Fmi::Exception exception(BCP, "Operation failed!", nullptr);
    exception.printError();

    return -1;
  }
}
<commit_msg>smartmetd.cpp: initialization task erro handling update<commit_after>#include "AsyncServer.h"

// #include <jemalloc/jemalloc.h>
#include <macgyver/AsyncTaskGroup.h>
#include <macgyver/AnsiEscapeCodes.h>
#include <macgyver/Exception.h>
#include <spine/HTTP.h>
#include <spine/Options.h>
#include <spine/Reactor.h>
#include <spine/SmartMet.h>
#include <spine/Convenience.h>
#include <sys/types.h>
#include <sys/select.h>
#include <atomic>
#include <csignal>
#include <iostream>
#include <memory>
#include <new>
#include <thread>

// libdw from elfutils-devel provides more details than libbfd
#define BACKWARD_HAS_DW 1
#include "backward.h"

std::unique_ptr<SmartMet::Server::Server> server;
std::unique_ptr<SmartMet::Spine::Reactor> reactor;
std::unique_ptr<Fmi::AsyncTaskGroup> tasks;

std::atomic<int> last_signal(0);

// Allowed core dump signals. Note that we choose to ignore SIGBUS though due to
// NFS problems, and SIGQUIT since we want to allow quitting via keyboard

std::vector<int> core_signals{SIGILL, SIGABRT, SIGFPE, SIGSYS, SIGSEGV, SIGXCPU, SIGXFSZ};

void crash_signal_handler(int sig)
{
  std::cout << "---------------------------------------------------------\n";
  std::cout << SmartMet::Spine::log_time_str() << " THE SYSTEM IS GOING DOWN (signal=" << sig << ")\n";
  std::cout << "---------------------------------------------------------\n";
  auto requests = reactor->getActiveRequests();
  for (auto it = requests.begin(); it != requests.end(); ++it)
  {
    std::cout << it->second.request.getURI() << "\n";
    std::cout << "---------------------------------------------------------\n";
  }
  signal(sig, SIG_DFL);
  raise(sig);
}

void signal_handler(int sig)
{
  last_signal = sig;
}
// Block all signals except profiling
void block_signals()
{
  sigset_t signal_set;
  sigfillset(&signal_set);

  // Enable debugging
  sigdelset(&signal_set, SIGPROF);

  // Enable core dumps from fatal errors
  for (auto sig : core_signals)
    sigdelset(&signal_set, sig);

  pthread_sigmask(SIG_BLOCK, &signal_set, nullptr);
}

void set_new_handler(const std::string& name)
{
  if (name == "default")  // system default may change in C++20
    ;
  else if (name == "bad_alloc")
    std::set_new_handler([] { throw std::bad_alloc(); });
  else if (name == "terminate")
    std::set_new_handler([] { std::terminate(); });
  else
    throw Fmi::Exception(BCP, "Unknown new_handler").addParameter("name", name);
}

int main(int argc, char* argv[])
{
  try
  {
    // Parse options

    SmartMet::Spine::Options options;
    if (!options.parse(argc, argv))
      exit(1);

    // Use the system locale or autocomplete may not work properly (iconv requirement)
    std::setlocale(LC_ALL, "");

    // Set new_handler
    set_new_handler(options.new_handler);

    const auto signals_init =
        [] ()
        {
            // Block signals before starting new threads

            block_signals();

            // Set special SIGTERM, SIGBUS and SIGWINCH handlers

            struct sigaction action;             // NOLINT(cppcoreguidelines-pro-type-member-init)
            action.sa_handler = signal_handler;  // NOLINT(cppcoreguidelines-pro-type-union-access)
            sigemptyset(&action.sa_mask);
            action.sa_flags = 0;
            sigaction(SIGBUS, &action, nullptr);
            sigaction(SIGTERM, &action, nullptr);
            sigaction(SIGWINCH, &action, nullptr);

            // We also want to record other common non-core dumping signals
            sigaction(SIGHUP, &action, nullptr);
            sigaction(SIGINT, &action, nullptr);

            struct sigaction action2;             // NOLINT(cppcoreguidelines-pro-type-member-init)
            action2.sa_handler = crash_signal_handler;  // NOLINT(cppcoreguidelines-pro-type-union-access)
            sigemptyset(&action2.sa_mask);
            action2.sa_flags = 0;
            sigaction(SIGSEGV, &action2, nullptr);

        };

    std::unique_ptr<backward::SignalHandling> sh;
    if (options.stacktrace)
      sh.reset(new backward::SignalHandling(core_signals));

    reactor.reset(new SmartMet::Spine::Reactor(options));

    server.reset(new SmartMet::Server::AsyncServer(options, *reactor));

    tasks.reset(new Fmi::AsyncTaskGroup);

    tasks->on_task_error(
        [] (const std::string&)
        {
           if (server)
           {
               server->shutdownServer();
           }
           else
           {
               throw;
           }
        });

    tasks->stop_on_error(true);

    tasks->add(
        "SmartMet::Spine::Reactor::init",
        [signals_init] ()
        {
            signals_init();
            reactor->init();
        });

    tasks->add(
        "Run SmartMet::Server::AsyncServer",
        [signals_init] ()
        {
            signals_init();
            std::this_thread::sleep_for(std::chrono::seconds(3));
            std::cout << ANSI_BG_GREEN << ANSI_BOLD_ON << ANSI_FG_WHITE << "Launched Synapse server"
                      << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT << std::endl;
            server->run();
        });

    // Sleep until a signal comes, and then either handle it or exit

    double sigint_cnt = 0;

    while (true)
    {
        struct timeval tv;
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        errno = 0;
        if (select(0, nullptr, nullptr, nullptr, &tv) >= 0) {
            tasks->handle_finished();
            // FIXME: handle case when all tasks have ended
        } else if (errno != EINTR) {
            std::cout << ANSI_BG_RED << ANSI_BOLD_ON << ANSI_FG_WHITE
                      << "Unexpected error code from select(): "
                      << strerror(errno)
                      << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                      << std::endl;
        }

        int sig = last_signal;
        if (sig != 0) {
            std::cout << "\n"
                      << ANSI_BG_RED << ANSI_BOLD_ON << ANSI_FG_WHITE << "Signal '"
                      << strsignal(sig) << "' (" << sig << ") received ";

            if (sig == SIGBUS || sig == SIGWINCH)
            {
                std::cout << " - ignoring it!"
                          << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                          << std::endl;
                last_signal = 0;
            }
            else if (sig == SIGTERM)
            {
                std::cout << " - shutting down!"
                          << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                          << std::endl;

                tasks->stop();
                server->shutdownServer();
                tasks->wait();

                // Save heap profile if it has been enabled
                // mallctl("prof.dump", nullptr, nullptr, nullptr, 0);
                return 0;
            }
            else if (sig == SIGINT)
            {
	        last_signal = 0;
                Fmi::AsyncTask shutdown_timer("Shutdown timer",
					      [&sigint_cnt]()
					      {
						  for (int i = 0; i < 1200; i++)
						  {
						      boost::this_thread::sleep_for(boost::chrono::milliseconds(50));
						      if (last_signal == SIGINT || last_signal == SIGTERM) {
							  last_signal = 0;
							  sigint_cnt++;
                                                          if (sigint_cnt > 5) {
							      std::cout << "*** Too many SIGINT or SIGTERM signals after first SIGINT. Commiting suicide" << std::endl;
							      abort();
							  }
						      } else {
							  sigint_cnt = std::max(0.0, sigint_cnt - 0.05);
						      }
						  }
						  std::cout << "*** Timed out waiting for server to shut down after SIGINT" << std::endl;
                                                  abort();
					      });
                std::cout << " - shutting down!"
                          << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                          << std::endl;

                tasks->stop();
                server->shutdownServer();
                tasks->wait();
		shutdown_timer.cancel();

                // Save heap profile if it has been enabled
                // mallctl("prof.dump", nullptr, nullptr, nullptr, 0);
                return 0;
            }
            else
            {
                std::cout << " - exiting!" << ANSI_FG_DEFAULT << ANSI_BOLD_OFF << ANSI_BG_DEFAULT
                          << std::endl;
                break;
            }
        }
    }

    return 666;
  }
  catch (...)
  {
    Fmi::Exception exception(BCP, "Operation failed!", nullptr);
    exception.printError();

    return -1;
  }
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#define SOFA_COMPONENT_ENGINE_VALUESFROMINDICES_CPP
#include <SofaEngine/ValuesFromIndices.inl>
#include <sofa/core/ObjectFactory.h>
#include <sofa/defaulttype/Vec3Types.h>
#include <sofa/defaulttype/RigidTypes.h>

namespace sofa
{

namespace component
{

namespace engine
{

SOFA_DECL_CLASS(ValuesFromIndices)

int ValuesFromIndicesClass = core::RegisterObject("Find the values given a list of indices")
        .add< ValuesFromIndices<std::string> >()
        .add< ValuesFromIndices<int> >()
        .add< ValuesFromIndices<unsigned int> >()
        .add< ValuesFromIndices< helper::fixed_array<unsigned int, 2> > >()
        .add< ValuesFromIndices< helper::fixed_array<unsigned int, 3> > >()
        .add< ValuesFromIndices< helper::fixed_array<unsigned int, 4> > >()
        .add< ValuesFromIndices< helper::fixed_array<unsigned int, 8> > >()
#ifndef SOFA_FLOAT
        .add< ValuesFromIndices<double> >()
        .add< ValuesFromIndices<defaulttype::Vec2d> >()
        .add< ValuesFromIndices<defaulttype::Vec3d> >()
		.add< ValuesFromIndices<defaulttype::Vec4d> >()
		.add< ValuesFromIndices<defaulttype::Vec6d> >()
        .add< ValuesFromIndices<defaulttype::Rigid2dTypes::Coord> >()
//.add< ValuesFromIndices<defaulttype::Rigid2dTypes::Deriv> >()  WARNING: removed because «duplicate instanciation» (changes on RigidDeriv)
        .add< ValuesFromIndices<defaulttype::Rigid3dTypes::Coord> >()
        .add< ValuesFromIndices<defaulttype::Rigid3dTypes::Deriv> >()
#endif //SOFA_FLOAT
#ifndef SOFA_DOUBLE
        .add< ValuesFromIndices<float> >()
        .add< ValuesFromIndices<defaulttype::Vec2f> >()
        .add< ValuesFromIndices<defaulttype::Vec3f> >()
		.add< ValuesFromIndices<defaulttype::Vec4f> >()
		.add< ValuesFromIndices<defaulttype::Vec6f> >()
        .add< ValuesFromIndices<defaulttype::Rigid2fTypes::Coord> >()
//.add< ValuesFromIndices<defaulttype::Rigid2fTypes::Deriv> >() WARNING: removed because «duplicate instanciation» (changes on RigidDeriv)
        .add< ValuesFromIndices<defaulttype::Rigid3fTypes::Coord> >()
        .add< ValuesFromIndices<defaulttype::Rigid3fTypes::Deriv> >()
#endif //SOFA_DOUBLE
        ;

template class SOFA_ENGINE_API ValuesFromIndices<std::string>;
template class SOFA_ENGINE_API ValuesFromIndices<int>;
template class SOFA_ENGINE_API ValuesFromIndices<unsigned int>;
template class SOFA_ENGINE_API ValuesFromIndices< helper::fixed_array<unsigned int, 2> >;
template class SOFA_ENGINE_API ValuesFromIndices< helper::fixed_array<unsigned int, 3> >;
template class SOFA_ENGINE_API ValuesFromIndices< helper::fixed_array<unsigned int, 4> >;
template class SOFA_ENGINE_API ValuesFromIndices< helper::fixed_array<unsigned int, 8> >;
#ifndef SOFA_FLOAT
template class SOFA_ENGINE_API ValuesFromIndices<double>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec2d>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec3d>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec4d>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec6d>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid2dTypes::Coord>;
//template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid2dTypes::Deriv>;   WARNING: removed because «duplicate instanciation» (???)
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid3dTypes::Coord>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid3dTypes::Deriv>;
#endif //SOFA_FLOAT
#ifndef SOFA_DOUBLE
template class SOFA_ENGINE_API ValuesFromIndices<float>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec2f>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec3f>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec4f>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec6f>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid2fTypes::Coord>;
//template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid2fTypes::Deriv>;   WARNING: removed because «duplicate instanciation» (???)
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid3fTypes::Coord>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid3fTypes::Deriv>;
#endif //SOFA_DOUBLE

} // namespace constraint

} // namespace component

} // namespace sofa

<commit_msg>SofaEngine/ValuesFromIndices: uncomment some instanciations<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#define SOFA_COMPONENT_ENGINE_VALUESFROMINDICES_CPP
#include <SofaEngine/ValuesFromIndices.inl>
#include <sofa/core/ObjectFactory.h>
#include <sofa/defaulttype/Vec3Types.h>
#include <sofa/defaulttype/RigidTypes.h>

namespace sofa
{

namespace component
{

namespace engine
{

SOFA_DECL_CLASS(ValuesFromIndices)

int ValuesFromIndicesClass = core::RegisterObject("Find the values given a list of indices")
        .add< ValuesFromIndices<std::string> >()
        .add< ValuesFromIndices<int> >()
        .add< ValuesFromIndices<unsigned int> >()
        .add< ValuesFromIndices< helper::fixed_array<unsigned int, 2> > >()
        .add< ValuesFromIndices< helper::fixed_array<unsigned int, 3> > >()
        .add< ValuesFromIndices< helper::fixed_array<unsigned int, 4> > >()
        .add< ValuesFromIndices< helper::fixed_array<unsigned int, 8> > >()
#ifndef SOFA_FLOAT
        .add< ValuesFromIndices<double> >()
        .add< ValuesFromIndices<defaulttype::Vec2d> >()
        .add< ValuesFromIndices<defaulttype::Vec3d> >()
		.add< ValuesFromIndices<defaulttype::Vec4d> >()
		.add< ValuesFromIndices<defaulttype::Vec6d> >()
        .add< ValuesFromIndices<defaulttype::Rigid2dTypes::Coord> >()
        .add< ValuesFromIndices<defaulttype::Rigid2dTypes::Deriv> >()
        .add< ValuesFromIndices<defaulttype::Rigid3dTypes::Coord> >()
        .add< ValuesFromIndices<defaulttype::Rigid3dTypes::Deriv> >()
#endif //SOFA_FLOAT
#ifndef SOFA_DOUBLE
        .add< ValuesFromIndices<float> >()
        .add< ValuesFromIndices<defaulttype::Vec2f> >()
        .add< ValuesFromIndices<defaulttype::Vec3f> >()
		.add< ValuesFromIndices<defaulttype::Vec4f> >()
		.add< ValuesFromIndices<defaulttype::Vec6f> >()
        .add< ValuesFromIndices<defaulttype::Rigid2fTypes::Coord> >()
        .add< ValuesFromIndices<defaulttype::Rigid2fTypes::Deriv> >()
        .add< ValuesFromIndices<defaulttype::Rigid3fTypes::Coord> >()
        .add< ValuesFromIndices<defaulttype::Rigid3fTypes::Deriv> >()
#endif //SOFA_DOUBLE
        ;

template class SOFA_ENGINE_API ValuesFromIndices<std::string>;
template class SOFA_ENGINE_API ValuesFromIndices<int>;
template class SOFA_ENGINE_API ValuesFromIndices<unsigned int>;
template class SOFA_ENGINE_API ValuesFromIndices< helper::fixed_array<unsigned int, 2> >;
template class SOFA_ENGINE_API ValuesFromIndices< helper::fixed_array<unsigned int, 3> >;
template class SOFA_ENGINE_API ValuesFromIndices< helper::fixed_array<unsigned int, 4> >;
template class SOFA_ENGINE_API ValuesFromIndices< helper::fixed_array<unsigned int, 8> >;
#ifndef SOFA_FLOAT
template class SOFA_ENGINE_API ValuesFromIndices<double>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec2d>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec3d>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec4d>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec6d>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid2dTypes::Coord>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid2dTypes::Deriv>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid3dTypes::Coord>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid3dTypes::Deriv>;
#endif //SOFA_FLOAT
#ifndef SOFA_DOUBLE
template class SOFA_ENGINE_API ValuesFromIndices<float>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec2f>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec3f>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec4f>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Vec6f>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid2fTypes::Coord>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid2fTypes::Deriv>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid3fTypes::Coord>;
template class SOFA_ENGINE_API ValuesFromIndices<defaulttype::Rigid3fTypes::Deriv>;
#endif //SOFA_DOUBLE

} // namespace constraint

} // namespace component

} // namespace sofa

<|endoftext|>