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

#include <exotica/TaskInitializer.h>
#include <exotica/Tasks.h>

namespace exotica
{
Task::Task()
{
}

void Task::initialize(const std::vector<exotica::Initializer>& inits, PlanningProblem_ptr prob, TaskSpaceVector& phi)
{
    for (const exotica::Initializer& init : inits)
    {
        TaskInitializer task(init);
        auto it = prob->getTaskMaps().find(task.Task);
        if (it == prob->getTaskMaps().end()) throw_pretty("Task map '" << task.Task << "' has not been defined!");
        TaskMaps[task.Task] = it->second;
        Tasks.push_back(it->second);
        TaskInitializers.push_back(task);
    }
    NumTasks = Tasks.size();
    PhiN = 0;
    JN = 0;
    phi.map.resize(0);
    Indexing.resize(Tasks.size());
    for (int i = 0; i < NumTasks; i++)
    {
        Indexing[i].Id = i;
        Indexing[i].Start = PhiN;
        Indexing[i].Length = Tasks[i]->Length;
        Indexing[i].StartJ = JN;
        Indexing[i].LengthJ = Tasks[i]->LengthJ;

        appendVector(phi.map, TaskVectorEntry::reindex(Tasks[i]->getLieGroupIndices(), Tasks[i]->Start, Indexing[i].Start));
        PhiN += Tasks[i]->Length;
        JN += Tasks[i]->LengthJ;
    }
    phi.setZero(PhiN);
}

EndPoseTask::EndPoseTask()
{
}

void EndPoseTask::initialize(const std::vector<exotica::Initializer>& inits, PlanningProblem_ptr prob, TaskSpaceVector& phi)
{
    Task::initialize(inits, prob, Phi);
    y = Phi;
    y.setZero(PhiN);
    Rho = Eigen::VectorXd::Ones(NumTasks);
    if (prob->getFlags() & KIN_J) J = Eigen::MatrixXd(JN, prob->N);
    if (prob->getFlags() & KIN_J_DOT) H.setConstant(JN, Eigen::MatrixXd::Zero(prob->N, prob->N));
    S = Eigen::MatrixXd::Identity(JN, JN);
    ydiff = Eigen::VectorXd::Zero(JN);

    for (int i = 0; i < NumTasks; i++)
    {
        TaskInitializer task(inits[i]);
        if (task.Goal.rows() == 0)
        {
            // Keep zero goal
        }
        else if (task.Goal.rows() == Tasks[i]->Length)
        {
            y.data.segment(Tasks[i]->Start, Tasks[i]->Length) = task.Goal;
        }
        else
        {
            throw_pretty("Invalid task goal size! Expecting " << Tasks[i]->Length << " got " << task.Goal.rows());
        }
        if (task.Rho.rows() == 0)
        {
            Rho(i) = 1.0;
        }
        else if (task.Rho.rows() == 1)
        {
            Rho(i) = task.Rho(0);
        }
        else
        {
            throw_pretty("Invalid task Rho size! Expecting 1 got " << task.Rho.rows());
        }
    }
}

void EndPoseTask::updateS()
{
    for (const TaskIndexing& task : Indexing)
    {
        for (int i = 0; i < task.LengthJ; i++)
        {
            S(i + task.Start, i + task.Start) = Rho(task.Id);
        }
        if (Rho(task.Id) != 0.0) Tasks[task.Id]->isUsed = true;
    }
}

void EndPoseTask::update(const TaskSpaceVector& bigPhi, Eigen::MatrixXdRefConst bigJ, HessianRefConst bigH)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi.data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
        J.middleRows(task.StartJ, task.LengthJ) = bigJ.middleRows(Tasks[task.Id]->StartJ, Tasks[task.Id]->LengthJ);
        H.segment(task.Start, task.Length) = bigH.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff = Phi - y;
}

void EndPoseTask::update(const TaskSpaceVector& bigPhi, Eigen::MatrixXdRefConst bigJ)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi.data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
        J.middleRows(task.StartJ, task.LengthJ) = bigJ.middleRows(Tasks[task.Id]->StartJ, Tasks[task.Id]->LengthJ);
    }
    ydiff = Phi - y;
}

void EndPoseTask::update(const TaskSpaceVector& bigPhi)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi.data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff = Phi - y;
}

TimeIndexedTask::TimeIndexedTask()
{
}

void TimeIndexedTask::initialize(const std::vector<exotica::Initializer>& inits, PlanningProblem_ptr prob, TaskSpaceVector& phi)
{
    Task::initialize(inits, prob, phi);
    phi.setZero(PhiN);
}

void TimeIndexedTask::updateS()
{
    for (int t = 0; t < T; t++)
    {
        for (const TaskIndexing& task : Indexing)
        {
            for (int i = 0; i < task.LengthJ; i++)
            {
                S[t](i + task.Start, i + task.Start) = Rho[t](task.Id);
            }
            if (Rho[t](task.Id) != 0.0) Tasks[task.Id]->isUsed = true;
        }
    }
}

void TimeIndexedTask::update(const TaskSpaceVector& bigPhi, Eigen::MatrixXdRefConst bigJ, HessianRefConst bigH, int t)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi[t].data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
        J[t].middleRows(task.StartJ, task.LengthJ) = bigJ.middleRows(Tasks[task.Id]->StartJ, Tasks[task.Id]->LengthJ);
        H[t].segment(task.Start, task.Length) = bigH.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff[t] = Phi[t] - y[t];
}

void TimeIndexedTask::update(const TaskSpaceVector& bigPhi, Eigen::MatrixXdRefConst bigJ, int t)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi[t].data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
        J[t].middleRows(task.StartJ, task.LengthJ) = bigJ.middleRows(Tasks[task.Id]->StartJ, Tasks[task.Id]->LengthJ);
    }
    ydiff[t] = Phi[t] - y[t];
}

void TimeIndexedTask::update(const TaskSpaceVector& bigPhi, int t)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi[t].data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff[t] = Phi[t] - y[t];
}

void TimeIndexedTask::reinitializeVariables(int T_in, PlanningProblem_ptr prob, const TaskSpaceVector& phi)
{
    T = T_in;
    Phi.assign(T, phi);
    y = Phi;
    Rho.assign(T, Eigen::VectorXd::Ones(NumTasks));
    if (prob->getFlags() & KIN_J) J.assign(T, Eigen::MatrixXd(JN, prob->N));
    if (prob->getFlags() & KIN_J_DOT)
    {
        Hessian Htmp;
        Htmp.setConstant(JN, Eigen::MatrixXd::Zero(prob->N, prob->N));
        H.assign(T, Htmp);
    }
    S.assign(T, Eigen::MatrixXd::Identity(JN, JN));
    ydiff.assign(T, Eigen::VectorXd::Zero(JN));

    if (NumTasks != TaskInitializers.size()) throw_pretty("Number of tasks does not match internal number of tasks!");
    for (int i = 0; i < NumTasks; i++)
    {
        TaskInitializer& task = TaskInitializers[i];
        if (task.Goal.rows() == 0)
        {
            // Keep zero goal
        }
        else if (task.Goal.rows() == Tasks[i]->Length * T)
        {
            for (int t = 0; t < T; t++)
            {
                y[t].data.segment(Tasks[i]->Start, Tasks[i]->Length) = task.Goal.segment(t * Tasks[i]->Length, Tasks[i]->Length);
            }
        }
        else if (task.Goal.rows() == Tasks[i]->Length)
        {
            for (int t = 0; t < T; t++)
            {
                y[t].data.segment(Tasks[i]->Start, Tasks[i]->Length) = task.Goal.segment(Tasks[i]->Length, Tasks[i]->Length);
            }
        }
        else
        {
            throw_pretty("Invalid task goal size! Expecting " << Tasks[i]->Length * T << " (or 1) and got " << task.Goal.rows());
        }
        if (task.Rho.rows() == 0)
        {
            // Keep ones
        }
        else if (task.Rho.rows() == T)
        {
            for (int t = 0; t < T; t++)
            {
                Rho[t](i) = task.Rho(t);
            }
        }
        else if (task.Rho.rows() == 1)
        {
            for (int t = 0; t < T; t++)
            {
                Rho[t](i) = task.Rho(0);
            }
        }
        else
        {
            throw_pretty("Invalid task Rho size! Expecting " << T << " (or 1) and got " << task.Rho.rows());
        }
    }
}

SamplingTask::SamplingTask()
{
}

void SamplingTask::initialize(const std::vector<exotica::Initializer>& inits, PlanningProblem_ptr prob, TaskSpaceVector& phi)
{
    Task::initialize(inits, prob, Phi);
    y = Phi;
    y.setZero(PhiN);
    Rho = Eigen::VectorXd::Ones(NumTasks);
    S = Eigen::MatrixXd::Identity(JN, JN);
    ydiff = Eigen::VectorXd::Zero(JN);

    for (int i = 0; i < NumTasks; i++)
    {
        TaskInitializer task(inits[i]);
        if (task.Goal.rows() == 0)
        {
            // Keep zero goal
        }
        else if (task.Goal.rows() == Tasks[i]->Length)
        {
            y.data.segment(Tasks[i]->Start, Tasks[i]->Length) = task.Goal;
        }
        else
        {
            throw_pretty("Invalid task goal size! Expecting " << Tasks[i]->Length << " got " << task.Goal.rows());
        }
        if (task.Rho.rows() == 0)
        {
            Rho(i) = 1.0;
        }
        else if (task.Rho.rows() == 1)
        {
            Rho(i) = task.Rho(0);
        }
        else
        {
            throw_pretty("Invalid task Rho size! Expecting 1 got " << task.Rho.rows());
        }
    }
}

void SamplingTask::updateS()
{
    for (const TaskIndexing& task : Indexing)
    {
        for (int i = 0; i < task.LengthJ; i++)
        {
            S(i + task.Start, i + task.Start) = Rho(task.Id);
        }
        if (Rho(task.Id) != 0.0) Tasks[task.Id]->isUsed = true;
    }
}

void SamplingTask::update(const TaskSpaceVector& bigPhi)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi.data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff = Phi - y;
}
}
<commit_msg>Tasks: Fix memory bug when initialising goals for tasks - Fixes #323<commit_after>/*
 *      Author: Vladimir Ivan
 *
 * Copyright (c) 2017, University Of Edinburgh
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of  nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <exotica/TaskInitializer.h>
#include <exotica/Tasks.h>

namespace exotica
{
Task::Task()
{
}

void Task::initialize(const std::vector<exotica::Initializer>& inits, PlanningProblem_ptr prob, TaskSpaceVector& phi)
{
    for (const exotica::Initializer& init : inits)
    {
        TaskInitializer task(init);
        auto it = prob->getTaskMaps().find(task.Task);
        if (it == prob->getTaskMaps().end()) throw_pretty("Task map '" << task.Task << "' has not been defined!");
        TaskMaps[task.Task] = it->second;
        Tasks.push_back(it->second);
        TaskInitializers.push_back(task);
    }
    NumTasks = Tasks.size();
    PhiN = 0;
    JN = 0;
    phi.map.resize(0);
    Indexing.resize(Tasks.size());
    for (int i = 0; i < NumTasks; i++)
    {
        Indexing[i].Id = i;
        Indexing[i].Start = PhiN;
        Indexing[i].Length = Tasks[i]->Length;
        Indexing[i].StartJ = JN;
        Indexing[i].LengthJ = Tasks[i]->LengthJ;

        appendVector(phi.map, TaskVectorEntry::reindex(Tasks[i]->getLieGroupIndices(), Tasks[i]->Start, Indexing[i].Start));
        PhiN += Tasks[i]->Length;
        JN += Tasks[i]->LengthJ;
    }
    phi.setZero(PhiN);
}

EndPoseTask::EndPoseTask()
{
}

void EndPoseTask::initialize(const std::vector<exotica::Initializer>& inits, PlanningProblem_ptr prob, TaskSpaceVector& phi)
{
    Task::initialize(inits, prob, Phi);
    y = Phi;
    y.setZero(PhiN);
    Rho = Eigen::VectorXd::Ones(NumTasks);
    if (prob->getFlags() & KIN_J) J = Eigen::MatrixXd(JN, prob->N);
    if (prob->getFlags() & KIN_J_DOT) H.setConstant(JN, Eigen::MatrixXd::Zero(prob->N, prob->N));
    S = Eigen::MatrixXd::Identity(JN, JN);
    ydiff = Eigen::VectorXd::Zero(JN);

    for (int i = 0; i < NumTasks; i++)
    {
        TaskInitializer task(inits[i]);
        if (task.Goal.rows() == 0)
        {
            // Keep zero goal
        }
        else if (task.Goal.rows() == Tasks[i]->Length)
        {
            y.data.segment(Indexing[i].Start, Indexing[i].Length) = task.Goal;
        }
        else
        {
            throw_pretty("Invalid task goal size! Expecting " << Tasks[i]->Length << " got " << task.Goal.rows());
        }
        if (task.Rho.rows() == 0)
        {
            Rho(i) = 1.0;
        }
        else if (task.Rho.rows() == 1)
        {
            Rho(i) = task.Rho(0);
        }
        else
        {
            throw_pretty("Invalid task Rho size! Expecting 1 got " << task.Rho.rows());
        }
    }
}

void EndPoseTask::updateS()
{
    for (const TaskIndexing& task : Indexing)
    {
        for (int i = 0; i < task.LengthJ; i++)
        {
            S(i + task.Start, i + task.Start) = Rho(task.Id);
        }
        if (Rho(task.Id) != 0.0) Tasks[task.Id]->isUsed = true;
    }
}

void EndPoseTask::update(const TaskSpaceVector& bigPhi, Eigen::MatrixXdRefConst bigJ, HessianRefConst bigH)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi.data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
        J.middleRows(task.StartJ, task.LengthJ) = bigJ.middleRows(Tasks[task.Id]->StartJ, Tasks[task.Id]->LengthJ);
        H.segment(task.Start, task.Length) = bigH.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff = Phi - y;
}

void EndPoseTask::update(const TaskSpaceVector& bigPhi, Eigen::MatrixXdRefConst bigJ)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi.data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
        J.middleRows(task.StartJ, task.LengthJ) = bigJ.middleRows(Tasks[task.Id]->StartJ, Tasks[task.Id]->LengthJ);
    }
    ydiff = Phi - y;
}

void EndPoseTask::update(const TaskSpaceVector& bigPhi)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi.data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff = Phi - y;
}

TimeIndexedTask::TimeIndexedTask()
{
}

void TimeIndexedTask::initialize(const std::vector<exotica::Initializer>& inits, PlanningProblem_ptr prob, TaskSpaceVector& phi)
{
    Task::initialize(inits, prob, phi);
    phi.setZero(PhiN);
}

void TimeIndexedTask::updateS()
{
    for (int t = 0; t < T; t++)
    {
        for (const TaskIndexing& task : Indexing)
        {
            for (int i = 0; i < task.LengthJ; i++)
            {
                S[t](i + task.Start, i + task.Start) = Rho[t](task.Id);
            }
            if (Rho[t](task.Id) != 0.0) Tasks[task.Id]->isUsed = true;
        }
    }
}

void TimeIndexedTask::update(const TaskSpaceVector& bigPhi, Eigen::MatrixXdRefConst bigJ, HessianRefConst bigH, int t)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi[t].data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
        J[t].middleRows(task.StartJ, task.LengthJ) = bigJ.middleRows(Tasks[task.Id]->StartJ, Tasks[task.Id]->LengthJ);
        H[t].segment(task.Start, task.Length) = bigH.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff[t] = Phi[t] - y[t];
}

void TimeIndexedTask::update(const TaskSpaceVector& bigPhi, Eigen::MatrixXdRefConst bigJ, int t)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi[t].data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
        J[t].middleRows(task.StartJ, task.LengthJ) = bigJ.middleRows(Tasks[task.Id]->StartJ, Tasks[task.Id]->LengthJ);
    }
    ydiff[t] = Phi[t] - y[t];
}

void TimeIndexedTask::update(const TaskSpaceVector& bigPhi, int t)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi[t].data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff[t] = Phi[t] - y[t];
}

void TimeIndexedTask::reinitializeVariables(int T_in, PlanningProblem_ptr prob, const TaskSpaceVector& phi)
{
    T = T_in;
    Phi.assign(T, phi);
    y = Phi;
    Rho.assign(T, Eigen::VectorXd::Ones(NumTasks));
    if (prob->getFlags() & KIN_J) J.assign(T, Eigen::MatrixXd(JN, prob->N));
    if (prob->getFlags() & KIN_J_DOT)
    {
        Hessian Htmp;
        Htmp.setConstant(JN, Eigen::MatrixXd::Zero(prob->N, prob->N));
        H.assign(T, Htmp);
    }
    S.assign(T, Eigen::MatrixXd::Identity(JN, JN));
    ydiff.assign(T, Eigen::VectorXd::Zero(JN));

    if (NumTasks != TaskInitializers.size()) throw_pretty("Number of tasks does not match internal number of tasks!");
    for (int i = 0; i < NumTasks; i++)
    {
        TaskInitializer& task = TaskInitializers[i];
        if (task.Goal.rows() == 0)
        {
            // Keep zero goal
        }
        else if (task.Goal.rows() == Tasks[i]->Length * T)
        {
            for (int t = 0; t < T; t++)
            {
                y[t].data.segment(Indexing[i].Start, Indexing[i].Length) = task.Goal.segment(t * Tasks[i]->Length, Tasks[i]->Length);
            }
        }
        else if (task.Goal.rows() == Tasks[i]->Length)
        {
            for (int t = 0; t < T; t++)
            {
                y[t].data.segment(Indexing[i].Start, Indexing[i].Length) = task.Goal.segment(Tasks[i]->Length, Tasks[i]->Length);
            }
        }
        else
        {
            throw_pretty("Invalid task goal size! Expecting " << Tasks[i]->Length * T << " (or 1) and got " << task.Goal.rows());
        }
        if (task.Rho.rows() == 0)
        {
            // Keep ones
        }
        else if (task.Rho.rows() == T)
        {
            for (int t = 0; t < T; t++)
            {
                Rho[t](i) = task.Rho(t);
            }
        }
        else if (task.Rho.rows() == 1)
        {
            for (int t = 0; t < T; t++)
            {
                Rho[t](i) = task.Rho(0);
            }
        }
        else
        {
            throw_pretty("Invalid task Rho size! Expecting " << T << " (or 1) and got " << task.Rho.rows());
        }
    }
}

SamplingTask::SamplingTask()
{
}

void SamplingTask::initialize(const std::vector<exotica::Initializer>& inits, PlanningProblem_ptr prob, TaskSpaceVector& phi)
{
    Task::initialize(inits, prob, Phi);
    y = Phi;
    y.setZero(PhiN);
    Rho = Eigen::VectorXd::Ones(NumTasks);
    S = Eigen::MatrixXd::Identity(JN, JN);
    ydiff = Eigen::VectorXd::Zero(JN);

    for (int i = 0; i < NumTasks; i++)
    {
        TaskInitializer task(inits[i]);
        if (task.Goal.rows() == 0)
        {
            // Keep zero goal
        }
        else if (task.Goal.rows() == Tasks[i]->Length)
        {
            y.data.segment(Indexing[i].Start, Indexing[i].Length) = task.Goal;
        }
        else
        {
            throw_pretty("Invalid task goal size! Expecting " << Tasks[i]->Length << " got " << task.Goal.rows());
        }
        if (task.Rho.rows() == 0)
        {
            Rho(i) = 1.0;
        }
        else if (task.Rho.rows() == 1)
        {
            Rho(i) = task.Rho(0);
        }
        else
        {
            throw_pretty("Invalid task Rho size! Expecting 1 got " << task.Rho.rows());
        }
    }
}

void SamplingTask::updateS()
{
    for (const TaskIndexing& task : Indexing)
    {
        for (int i = 0; i < task.LengthJ; i++)
        {
            S(i + task.Start, i + task.Start) = Rho(task.Id);
        }
        if (Rho(task.Id) != 0.0) Tasks[task.Id]->isUsed = true;
    }
}

void SamplingTask::update(const TaskSpaceVector& bigPhi)
{
    for (const TaskIndexing& task : Indexing)
    {
        Phi.data.segment(task.Start, task.Length) = bigPhi.data.segment(Tasks[task.Id]->Start, Tasks[task.Id]->Length);
    }
    ydiff = Phi - y;
}
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
 */

/*  This file is part of Ragel.
 *
 *  Ragel is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Ragel 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Ragel; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "rlcodegen.h"
#include "gvdotgen.h"
#include "gendata.h"

using namespace std;

std::ostream &GraphvizDotGen::KEY( Key key )
{
	if ( printPrintables && key.isPrintable() ) {
		// Output values as characters, ensuring we escape the quote (") character
		char cVal = (char) key.getVal();
		out << "'";
		switch ( cVal ) {
			case '"': case '\\':
				out << "\\" << cVal;
				break;
			case '\a':
				out << "\\\\a";
				break;
			case '\b':
				out << "\\\\b";
				break;
			case '\t':
				out << "\\\\t";
				break;
			case '\n':
				out << "\\\\n";
				break;
			case '\v':
				out << "\\\\v";
				break;
			case '\f':
				out << "\\\\f";
				break;
			case '\r':
				out << "\\\\r";
				break;
			default:
				out << cVal;
				break;
		}
		out << "'";
	}
	else {
		if ( keyOps->isSigned )
			out << key.getVal();
		else
			out << (unsigned long) key.getVal();
	}

	return out;
}

std::ostream &GraphvizDotGen::TRANS_ACTION( RedStateAp *fromState, RedTransAp *trans )
{
	int n = 0;
	RedAction *actions[3];

	if ( fromState->fromStateAction != 0 )
		actions[n++] = fromState->fromStateAction;
	if ( trans->action != 0 )
		actions[n++] = trans->action;
	if ( trans->targ != 0 && trans->targ->toStateAction != 0 )
		actions[n++] = trans->targ->toStateAction;

	if ( n > 0 )
		out << " / ";

	/* Loop the existing actions and write out what's there. */
	for ( int a = 0; a < n; a++ ) {
		for ( ActionTable::Iter actIt = actions[a]->key.first(); actIt.lte(); actIt++ ) {
			Action *action = actIt->value;
			out << action->nameOrLoc();
			if ( a < n-1 || !actIt.last() )
				out << ", ";
		}
	}
	return out;
}

std::ostream &GraphvizDotGen::ACTION( RedAction *action )
{
	/* The action. */
	out << " / ";
	for ( ActionTable::Iter actIt = action->key.first(); actIt.lte(); actIt++ ) {
		Action *action = actIt->value;
		if ( action->name != 0 )
			out << action->name;
		else
			out << action->loc.line << ":" << action->loc.col;
		if ( !actIt.last() )
			out << ", ";
	}
	return out;
}

std::ostream &GraphvizDotGen::ONCHAR( Key lowKey, Key highKey )
{
	if ( lowKey > keyOps->maxKey ) {
		CondSpace *condSpace = findCondSpace( lowKey, highKey );
		Key values = ( lowKey - condSpace->baseKey ) / keyOps->alphSize();

		lowKey = keyOps->minKey +
			(lowKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
		highKey = keyOps->minKey +
			(highKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
		KEY( lowKey );
		if ( lowKey != highKey ) {
			out << "..";
			KEY( highKey );
		}
		out << "(";

		for ( CondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
			bool set = values & (1 << csi.pos());
			if ( !set )
				out << "!";
			out << (*csi)->nameOrLoc();
			if ( !csi.last() )
				out << ", ";
		}
		out << ")";
	}
	else {
		/* Output the key. Possibly a range. */
		KEY( lowKey );
		if ( highKey != lowKey ) {
			out << "..";
			KEY( highKey );
		}
	}
	return out;
}

void GraphvizDotGen::writeTransList( RedStateAp *state )
{
	/* Build the set of unique transitions out of this state. */
	RedTransSet stTransSet;
	for ( RedTransList::Iter tel = state->outRange; tel.lte(); tel++ ) {
		/* If we haven't seen the transitions before, the move forward
		 * emitting all the transitions on the same character. */
		if ( stTransSet.insert( tel->value ) ) {
			/* Write out the from and to states. */
			out << "\t" << state->id << " -> ";

			if ( tel->value->targ == 0 )
				out << "err_" << state->id;
			else
				out << tel->value->targ->id;

			/* Begin the label. */
			out << " [ label = \"";
			ONCHAR( tel->lowKey, tel->highKey );

			/* Walk the transition list, finding the same. */
			for ( RedTransList::Iter mtel = tel.next(); mtel.lte(); mtel++ ) {
				if ( mtel->value == tel->value ) {
					out << ", ";
					ONCHAR( mtel->lowKey, mtel->highKey );
				}
			}

			/* Write the action and close the transition. */
			TRANS_ACTION( state, tel->value );
			out << "\" ];\n";
		}
	}

	/* Write the default transition. */
	if ( state->defTrans != 0 ) {
		/* Write out the from and to states. */
		out << "\t" << state->id << " -> ";

		if ( state->defTrans->targ == 0 )
			out << "err_" << state->id;
		else
			out << state->defTrans->targ->id;

		/* Begin the label. */
		out << " [ label = \"DEF";

		/* Write the action and close the transition. */
		TRANS_ACTION( state, state->defTrans );
		out << "\" ];\n";
	}
}

void GraphvizDotGen::writeDotFile( )
{
	out <<
		"digraph " << fsmName << " {\n"
		"	rankdir=LR;\n";

	/* Define the psuedo states. Transitions will be done after the states
	 * have been defined as either final or not final. */
	out << "	node [ shape = point ];\n";
	out << "	ENTRY;\n";

	/* Psuedo states for entry points in the entry map. */
	for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) {
		RedStateAp *state = allStates + *en;
		out << "	en_" << state->id << ";\n";
	}

	/* Psuedo states for final states with eof actions. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofAction != 0 )
			out << "	eof_" << st->id << ";\n";
	}

	out << "	node [ shape = circle, height = 0.2 ];\n";

	/* Psuedo states for states whose default actions go to error. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		bool needsErr = false;
		if ( st->defTrans != 0 && st->defTrans->targ == 0 )
			needsErr = true;
		else {
			for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) {
				if ( tel->value->targ == 0 ) {
					needsErr = true;
					break;
				}
			}
		}

		if ( needsErr )
			out << "	err_" << st->id << " [ label=\"\"];\n";
	}

	/* Attributes common to all nodes, plus double circle for final states. */
	out << "	node [ fixedsize = true, height = 0.65, shape = doublecircle ];\n";

	/* List Final states. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->isFinal )
			out << "	" << st->id << ";\n";
	}

	/* List transitions. */
	out << "	node [ shape = circle ];\n";

	/* Walk the states. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
		writeTransList( st );

	/* Transitions into the start state. */
	out << "	ENTRY -> " << redFsm->startState->id << " [ label = \"IN";
	out << "\" ];\n";

	/* Transitions into the entry points. */
	for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) {
		RedStateAp *state = allStates + *en;
		char *name = entryPointNames[en.pos()];
		out << "	en_" << state->id << " -> " << state->id <<
				" [ label = \"" << name << "\" ];\n";
	}

	/* Out action transitions. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofAction != 0 ) {
			out << "	" << st->id << " -> eof_" <<
					st->id << " [ label = \"EOF";
			ACTION( st->eofAction ) << "\" ];\n";
		}
	}

	out <<
		"}\n";
}

void GraphvizDotGen::finishRagelDef()
{
	assert( outputFormat == OutGraphvizDot );
	if ( !graphvizDone ) {
		graphvizDone = true;

		/* For dot file generation we want to pick default transitions. */
		redFsm->chooseDefaultSpan();

		/* Write out with it. */
		writeDotFile();
	}
}
<commit_msg>When displaying printables in graphviz output, print 32 as SP.<commit_after>/*
 *  Copyright 2001-2007 Adrian Thurston <thurston@cs.queensu.ca>
 */

/*  This file is part of Ragel.
 *
 *  Ragel is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Ragel 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Ragel; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "rlcodegen.h"
#include "gvdotgen.h"
#include "gendata.h"

using namespace std;

std::ostream &GraphvizDotGen::KEY( Key key )
{
	if ( printPrintables && key.isPrintable() ) {
		// Output values as characters, ensuring we escape the quote (") character
		char cVal = (char) key.getVal();
		switch ( cVal ) {
			case '"': case '\\':
				out << "'\\" << cVal << "'";
				break;
			case '\a':
				out << "'\\\\a'";
				break;
			case '\b':
				out << "'\\\\b'";
				break;
			case '\t':
				out << "'\\\\t'";
				break;
			case '\n':
				out << "'\\\\n'";
				break;
			case '\v':
				out << "'\\\\v'";
				break;
			case '\f':
				out << "'\\\\f'";
				break;
			case '\r':
				out << "'\\\\r'";
				break;
			case ' ':
				out << "SP";
				break;
			default:
				out << "'" << cVal << "'";
				break;
		}
	}
	else {
		if ( keyOps->isSigned )
			out << key.getVal();
		else
			out << (unsigned long) key.getVal();
	}

	return out;
}

std::ostream &GraphvizDotGen::TRANS_ACTION( RedStateAp *fromState, RedTransAp *trans )
{
	int n = 0;
	RedAction *actions[3];

	if ( fromState->fromStateAction != 0 )
		actions[n++] = fromState->fromStateAction;
	if ( trans->action != 0 )
		actions[n++] = trans->action;
	if ( trans->targ != 0 && trans->targ->toStateAction != 0 )
		actions[n++] = trans->targ->toStateAction;

	if ( n > 0 )
		out << " / ";

	/* Loop the existing actions and write out what's there. */
	for ( int a = 0; a < n; a++ ) {
		for ( ActionTable::Iter actIt = actions[a]->key.first(); actIt.lte(); actIt++ ) {
			Action *action = actIt->value;
			out << action->nameOrLoc();
			if ( a < n-1 || !actIt.last() )
				out << ", ";
		}
	}
	return out;
}

std::ostream &GraphvizDotGen::ACTION( RedAction *action )
{
	/* The action. */
	out << " / ";
	for ( ActionTable::Iter actIt = action->key.first(); actIt.lte(); actIt++ ) {
		Action *action = actIt->value;
		if ( action->name != 0 )
			out << action->name;
		else
			out << action->loc.line << ":" << action->loc.col;
		if ( !actIt.last() )
			out << ", ";
	}
	return out;
}

std::ostream &GraphvizDotGen::ONCHAR( Key lowKey, Key highKey )
{
	if ( lowKey > keyOps->maxKey ) {
		CondSpace *condSpace = findCondSpace( lowKey, highKey );
		Key values = ( lowKey - condSpace->baseKey ) / keyOps->alphSize();

		lowKey = keyOps->minKey +
			(lowKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
		highKey = keyOps->minKey +
			(highKey - condSpace->baseKey - keyOps->alphSize() * values.getVal());
		KEY( lowKey );
		if ( lowKey != highKey ) {
			out << "..";
			KEY( highKey );
		}
		out << "(";

		for ( CondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
			bool set = values & (1 << csi.pos());
			if ( !set )
				out << "!";
			out << (*csi)->nameOrLoc();
			if ( !csi.last() )
				out << ", ";
		}
		out << ")";
	}
	else {
		/* Output the key. Possibly a range. */
		KEY( lowKey );
		if ( highKey != lowKey ) {
			out << "..";
			KEY( highKey );
		}
	}
	return out;
}

void GraphvizDotGen::writeTransList( RedStateAp *state )
{
	/* Build the set of unique transitions out of this state. */
	RedTransSet stTransSet;
	for ( RedTransList::Iter tel = state->outRange; tel.lte(); tel++ ) {
		/* If we haven't seen the transitions before, the move forward
		 * emitting all the transitions on the same character. */
		if ( stTransSet.insert( tel->value ) ) {
			/* Write out the from and to states. */
			out << "\t" << state->id << " -> ";

			if ( tel->value->targ == 0 )
				out << "err_" << state->id;
			else
				out << tel->value->targ->id;

			/* Begin the label. */
			out << " [ label = \"";
			ONCHAR( tel->lowKey, tel->highKey );

			/* Walk the transition list, finding the same. */
			for ( RedTransList::Iter mtel = tel.next(); mtel.lte(); mtel++ ) {
				if ( mtel->value == tel->value ) {
					out << ", ";
					ONCHAR( mtel->lowKey, mtel->highKey );
				}
			}

			/* Write the action and close the transition. */
			TRANS_ACTION( state, tel->value );
			out << "\" ];\n";
		}
	}

	/* Write the default transition. */
	if ( state->defTrans != 0 ) {
		/* Write out the from and to states. */
		out << "\t" << state->id << " -> ";

		if ( state->defTrans->targ == 0 )
			out << "err_" << state->id;
		else
			out << state->defTrans->targ->id;

		/* Begin the label. */
		out << " [ label = \"DEF";

		/* Write the action and close the transition. */
		TRANS_ACTION( state, state->defTrans );
		out << "\" ];\n";
	}
}

void GraphvizDotGen::writeDotFile( )
{
	out <<
		"digraph " << fsmName << " {\n"
		"	rankdir=LR;\n";

	/* Define the psuedo states. Transitions will be done after the states
	 * have been defined as either final or not final. */
	out << "	node [ shape = point ];\n";
	out << "	ENTRY;\n";

	/* Psuedo states for entry points in the entry map. */
	for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) {
		RedStateAp *state = allStates + *en;
		out << "	en_" << state->id << ";\n";
	}

	/* Psuedo states for final states with eof actions. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofAction != 0 )
			out << "	eof_" << st->id << ";\n";
	}

	out << "	node [ shape = circle, height = 0.2 ];\n";

	/* Psuedo states for states whose default actions go to error. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		bool needsErr = false;
		if ( st->defTrans != 0 && st->defTrans->targ == 0 )
			needsErr = true;
		else {
			for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) {
				if ( tel->value->targ == 0 ) {
					needsErr = true;
					break;
				}
			}
		}

		if ( needsErr )
			out << "	err_" << st->id << " [ label=\"\"];\n";
	}

	/* Attributes common to all nodes, plus double circle for final states. */
	out << "	node [ fixedsize = true, height = 0.65, shape = doublecircle ];\n";

	/* List Final states. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->isFinal )
			out << "	" << st->id << ";\n";
	}

	/* List transitions. */
	out << "	node [ shape = circle ];\n";

	/* Walk the states. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
		writeTransList( st );

	/* Transitions into the start state. */
	out << "	ENTRY -> " << redFsm->startState->id << " [ label = \"IN";
	out << "\" ];\n";

	/* Transitions into the entry points. */
	for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ ) {
		RedStateAp *state = allStates + *en;
		char *name = entryPointNames[en.pos()];
		out << "	en_" << state->id << " -> " << state->id <<
				" [ label = \"" << name << "\" ];\n";
	}

	/* Out action transitions. */
	for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
		if ( st->eofAction != 0 ) {
			out << "	" << st->id << " -> eof_" <<
					st->id << " [ label = \"EOF";
			ACTION( st->eofAction ) << "\" ];\n";
		}
	}

	out <<
		"}\n";
}

void GraphvizDotGen::finishRagelDef()
{
	assert( outputFormat == OutGraphvizDot );
	if ( !graphvizDone ) {
		graphvizDone = true;

		/* For dot file generation we want to pick default transitions. */
		redFsm->chooseDefaultSpan();

		/* Write out with it. */
		writeDotFile();
	}
}
<|endoftext|>


<commit_before>#pragma once
#include <Windows.h>
#include <string>
#include <memory>

#pragma comment(lib, "Advapi32.lib")

namespace WinApiHelper
{
	class Registry
	{
		HKEY _hKey = 0;
		void Close()
		{
			if (_hKey != 0)
			{
				::RegCloseKey(_hKey);
				_hKey = 0;
			}
		}

	public:
		enum class Mode
		{
			Read = KEY_READ,
			Write = KEY_WRITE
		};

		enum class ValueType
		{
			none                       = 0,   // No value type
			sz                         = 1,   // Unicode nul terminated string
			expand_sz                  = 2,   // Unicode nul terminated string
			// (with environment variable references)
			binary                     = 3,   // Free form binary
			dword                      = 4,   // 32-bit number
			dword_little_endian        = 4,   // 32-bit number (same as REG_DWORD)
			dword_big_endian           = 5,   // 32-bit number
			link                       = 6,   // Symbolic Link (unicode)
			multi_sz                   = 7,   // Multiple Unicode strings
			resource_list              = 8,   // Resource list in the resource map
			full_resource_descriptor   = 9,  // Resource list in the hardware description
			resource_requirements_list = 10,
			qword                      = 11,  // 64-bit number
			qword_little_endian        = 11,   // 64-bit number (same as REG_QWORD)
		};

		Registry() {}
		~Registry()
		{
			Close();
		}

		DWORD Open(HKEY hKey, std::wstring const& subKey, Mode mode)
		{
			Close();
			return ::RegOpenKeyExW(hKey, subKey.c_str(), 0, static_cast<REGSAM>(mode), &_hKey);
		}

		DWORD TryReadString(std::wstring const& name, std::wstring& value)
		{
			DWORD requiredSize = 0;
			auto result = ::RegQueryValueExW(_hKey, name.c_str(), 0, nullptr, nullptr, &requiredSize);
			if (result != ERROR_SUCCESS) return result;

			requiredSize += sizeof(wchar_t);  // additional termination char
			std::unique_ptr<BYTE[]> pBuffer(new BYTE[requiredSize]);
			::SecureZeroMemory(pBuffer.get(), requiredSize);
			result = ::RegQueryValueExW(_hKey, name.c_str(), 0, nullptr, pBuffer.get(), &requiredSize);
			if (result == ERROR_SUCCESS)
			{
				value.swap(std::wstring(reinterpret_cast<wchar_t*>(pBuffer.get())));
			}

			return result;
		}

		static bool TryReadString(HKEY hKey, std::wstring const& subKey, std::wstring const& name, std::wstring& value)
		{
			Registry reg;
			if (reg.Open(hKey, subKey, Mode::Read) != ERROR_SUCCESS) return false;
			return reg.TryReadString(name, value) == ERROR_SUCCESS;
		}

		DWORD TryReadDword(std::wstring const& name, DWORD& value)
		{
			DWORD resultVal = 0;
			DWORD size = sizeof(resultVal);
			auto result = ::RegQueryValueExW(_hKey, name.c_str(), 0, nullptr, reinterpret_cast<BYTE*>(&resultVal), &size);
			if (result != ERROR_SUCCESS) return result;

			value = resultVal;
			return result;
		}

		static bool TryReadDword(HKEY hKey, std::wstring const& subKey, std::wstring const& name, DWORD& value)
		{
			Registry reg;
			if (reg.Open(hKey, subKey, Mode::Read) != ERROR_SUCCESS) return false;
			return reg.TryReadDword(name, value) == ERROR_SUCCESS;
		}
	};

}
<commit_msg>Registry: added EnumKeys member<commit_after>#pragma once
#include <Windows.h>
#include <string>
#include <vector>
#include <memory>

#pragma comment(lib, "Advapi32.lib")

namespace WinApiHelper
{
	class Registry
	{
		HKEY _hKey = 0;
		void Close()
		{
			if (_hKey != 0)
			{
				::RegCloseKey(_hKey);
				_hKey = 0;
			}
		}

	public:
		enum class Mode
		{
			Read = KEY_READ,
			Write = KEY_WRITE
		};

		enum class ValueType
		{
			none                       = 0,   // No value type
			sz                         = 1,   // Unicode nul terminated string
			expand_sz                  = 2,   // Unicode nul terminated string
			// (with environment variable references)
			binary                     = 3,   // Free form binary
			dword                      = 4,   // 32-bit number
			dword_little_endian        = 4,   // 32-bit number (same as REG_DWORD)
			dword_big_endian           = 5,   // 32-bit number
			link                       = 6,   // Symbolic Link (unicode)
			multi_sz                   = 7,   // Multiple Unicode strings
			resource_list              = 8,   // Resource list in the resource map
			full_resource_descriptor   = 9,  // Resource list in the hardware description
			resource_requirements_list = 10,
			qword                      = 11,  // 64-bit number
			qword_little_endian        = 11,   // 64-bit number (same as REG_QWORD)
		};

		Registry() {}
		~Registry()
		{
			Close();
		}

		DWORD Open(HKEY hKey, std::wstring const& subKey, Mode mode)
		{
			Close();
			return ::RegOpenKeyExW(hKey, subKey.c_str(), 0, static_cast<REGSAM>(mode), &_hKey);
		}

		DWORD EnumKeys(std::vector<std::wstring>& subKeys)
		{
			DWORD nSubKey = 0;
			DWORD maxSubKeyLen = 0;
			DWORD ret = ::RegQueryInfoKey(_hKey, NULL, NULL, 0, &nSubKey, &maxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
			if (ret != ERROR_SUCCESS) return ret;
			std::vector<wchar_t> buffer(maxSubKeyLen + 1, 0);
			DWORD index = 0;
			DWORD keyLen = maxSubKeyLen + 1;
			std::vector<std::wstring> values;
			ret = ::RegEnumKeyExW(_hKey, index++, &buffer[0], &keyLen, 0, NULL, NULL, NULL);
			while (ret == ERROR_SUCCESS)
			{
				values.push_back(std::wstring(&buffer[0], keyLen));
				keyLen = maxSubKeyLen + 1;
				ret = ::RegEnumKeyExW(_hKey, index++, &buffer[0], &keyLen, 0, NULL, NULL, NULL);
			}

			if (ret != ERROR_NO_MORE_ITEMS) return ret;
			subKeys.swap(values);
			return ERROR_SUCCESS;
		}

		DWORD TryReadString(std::wstring const& name, std::wstring& value)
		{
			DWORD requiredSize = 0;
			auto result = ::RegQueryValueExW(_hKey, name.c_str(), 0, nullptr, nullptr, &requiredSize);
			if (result != ERROR_SUCCESS) return result;

			requiredSize += sizeof(wchar_t);  // additional termination char
			std::unique_ptr<BYTE[]> pBuffer(new BYTE[requiredSize]);
			::SecureZeroMemory(pBuffer.get(), requiredSize);
			result = ::RegQueryValueExW(_hKey, name.c_str(), 0, nullptr, pBuffer.get(), &requiredSize);
			if (result == ERROR_SUCCESS)
			{
				value.swap(std::wstring(reinterpret_cast<wchar_t*>(pBuffer.get())));
			}

			return result;
		}

		static bool TryReadString(HKEY hKey, std::wstring const& subKey, std::wstring const& name, std::wstring& value)
		{
			Registry reg;
			if (reg.Open(hKey, subKey, Mode::Read) != ERROR_SUCCESS) return false;
			return reg.TryReadString(name, value) == ERROR_SUCCESS;
		}

		DWORD TryReadDword(std::wstring const& name, DWORD& value)
		{
			DWORD resultVal = 0;
			DWORD size = sizeof(resultVal);
			auto result = ::RegQueryValueExW(_hKey, name.c_str(), 0, nullptr, reinterpret_cast<BYTE*>(&resultVal), &size);
			if (result != ERROR_SUCCESS) return result;

			value = resultVal;
			return result;
		}

		static bool TryReadDword(HKEY hKey, std::wstring const& subKey, std::wstring const& name, DWORD& value)
		{
			Registry reg;
			if (reg.Open(hKey, subKey, Mode::Read) != ERROR_SUCCESS) return false;
			return reg.TryReadDword(name, value) == ERROR_SUCCESS;
		}
	};

}
<|endoftext|>


<commit_before>#pragma once

// `krbn::device_observer` can be used safely in a multi-threaded environment.

#include "boost_defs.hpp"

#include "grabbable_state_manager.hpp"
#include "grabber_client.hpp"
#include "hid_manager.hpp"
#include "hid_observer.hpp"
#include "logger.hpp"
#include "types.hpp"

namespace krbn {
class device_observer final {
public:
  device_observer(const device_observer&) = delete;

  device_observer(std::weak_ptr<grabber_client> grabber_client) : grabber_client_(grabber_client),
                                                                  hid_manager_({
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_keyboard),
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_mouse),
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_pointer),
                                                                  }) {
    grabbable_state_manager_.grabbable_state_changed.connect([this](auto&& grabbable_state) {
      if (auto client = grabber_client_.lock()) {
        client->grabbable_state_changed(grabbable_state);
      }
    });

    hid_manager_.device_detecting.connect([](auto&& device) {
      if (iokit_utility::is_karabiner_virtual_hid_device(device)) {
        return false;
      }

      iokit_utility::log_matching_device(device);

      return true;
    });

    hid_manager_.device_detected.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is detected.", human_interface_device->get_name_for_log());

      grabbable_state_manager_.update(grabbable_state(human_interface_device->get_registry_entry_id(),
                                                      grabbable_state::state::device_error,
                                                      grabbable_state::ungrabbable_temporarily_reason::none,
                                                      mach_absolute_time()));

      human_interface_device->values_arrived.connect([this](auto&& human_interface_device,
                                                            auto&& event_queue) {
        grabbable_state_manager_.update(event_queue);
      });

      auto observer = std::make_shared<hid_observer>(human_interface_device);

      observer->device_observed.connect([this](auto&& human_interface_device) {
        logger::get_logger().info("{0} is observed.",
                                  human_interface_device->get_name_for_log());

        if (auto state = grabbable_state_manager_.get_grabbable_state(human_interface_device->get_registry_entry_id())) {
          // Keep grabbable_state if the state is already changed by value_callback.
          if (state->get_state() == grabbable_state::state::device_error) {
            grabbable_state_manager_.update(grabbable_state(human_interface_device->get_registry_entry_id(),
                                                            grabbable_state::state::grabbable,
                                                            grabbable_state::ungrabbable_temporarily_reason::none,
                                                            mach_absolute_time()));
          }
        }
      });

      observer->observe();

      hid_observers_[human_interface_device->get_registry_entry_id()] = observer;
    });

    hid_manager_.device_removed.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is removed.", human_interface_device->get_name_for_log());

      hid_observers_.erase(human_interface_device->get_registry_entry_id());
    });

    hid_manager_.start();

    logger::get_logger().info("device_observer is started.");
  }

  ~device_observer(void) {
    hid_observers_.clear();
    hid_manager_.stop();

    logger::get_logger().info("device_observer is stopped.");
  }

private:
  std::weak_ptr<grabber_client> grabber_client_;

  hid_manager hid_manager_;
  std::unordered_map<registry_entry_id, std::shared_ptr<hid_observer>> hid_observers_;
  grabbable_state_manager grabbable_state_manager_;
};
} // namespace krbn
<commit_msg>clear hid_observers_ after hid_manager_.stop()<commit_after>#pragma once

// `krbn::device_observer` can be used safely in a multi-threaded environment.

#include "boost_defs.hpp"

#include "grabbable_state_manager.hpp"
#include "grabber_client.hpp"
#include "hid_manager.hpp"
#include "hid_observer.hpp"
#include "logger.hpp"
#include "types.hpp"

namespace krbn {
class device_observer final {
public:
  device_observer(const device_observer&) = delete;

  device_observer(std::weak_ptr<grabber_client> grabber_client) : grabber_client_(grabber_client),
                                                                  hid_manager_({
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_keyboard),
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_mouse),
                                                                      std::make_pair(hid_usage_page::generic_desktop, hid_usage::gd_pointer),
                                                                  }) {
    grabbable_state_manager_.grabbable_state_changed.connect([this](auto&& grabbable_state) {
      if (auto client = grabber_client_.lock()) {
        client->grabbable_state_changed(grabbable_state);
      }
    });

    hid_manager_.device_detecting.connect([](auto&& device) {
      if (iokit_utility::is_karabiner_virtual_hid_device(device)) {
        return false;
      }

      iokit_utility::log_matching_device(device);

      return true;
    });

    hid_manager_.device_detected.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is detected.", human_interface_device->get_name_for_log());

      grabbable_state_manager_.update(grabbable_state(human_interface_device->get_registry_entry_id(),
                                                      grabbable_state::state::device_error,
                                                      grabbable_state::ungrabbable_temporarily_reason::none,
                                                      mach_absolute_time()));

      human_interface_device->values_arrived.connect([this](auto&& human_interface_device,
                                                            auto&& event_queue) {
        grabbable_state_manager_.update(event_queue);
      });

      auto observer = std::make_shared<hid_observer>(human_interface_device);

      observer->device_observed.connect([this](auto&& human_interface_device) {
        logger::get_logger().info("{0} is observed.",
                                  human_interface_device->get_name_for_log());

        if (auto state = grabbable_state_manager_.get_grabbable_state(human_interface_device->get_registry_entry_id())) {
          // Keep grabbable_state if the state is already changed by value_callback.
          if (state->get_state() == grabbable_state::state::device_error) {
            grabbable_state_manager_.update(grabbable_state(human_interface_device->get_registry_entry_id(),
                                                            grabbable_state::state::grabbable,
                                                            grabbable_state::ungrabbable_temporarily_reason::none,
                                                            mach_absolute_time()));
          }
        }
      });

      observer->observe();

      hid_observers_[human_interface_device->get_registry_entry_id()] = observer;
    });

    hid_manager_.device_removed.connect([this](auto&& human_interface_device) {
      logger::get_logger().info("{0} is removed.", human_interface_device->get_name_for_log());

      hid_observers_.erase(human_interface_device->get_registry_entry_id());
    });

    hid_manager_.start();

    logger::get_logger().info("device_observer is started.");
  }

  ~device_observer(void) {
    hid_manager_.stop();
    hid_observers_.clear();

    logger::get_logger().info("device_observer is stopped.");
  }

private:
  std::weak_ptr<grabber_client> grabber_client_;

  hid_manager hid_manager_;
  std::unordered_map<registry_entry_id, std::shared_ptr<hid_observer>> hid_observers_;
  grabbable_state_manager grabbable_state_manager_;
};
} // namespace krbn
<|endoftext|>


<commit_before>#include "msnapshotitem.h"

#include <QGraphicsScene>
#include <QImage>
#include <QPainter>
#include <QApplication>
#include <QGraphicsView>

MSnapshotItem::MSnapshotItem(const QRectF &sceneTargetRect, QGraphicsItem *parent)
    : QGraphicsObject(parent), m_boundingRect(sceneTargetRect)
{
}

MSnapshotItem::~MSnapshotItem()
{
}

QRectF MSnapshotItem::boundingRect() const
{
    return m_boundingRect;
}

void MSnapshotItem::updateSnapshot()
{
    if (scene() && scene()->views().count() > 0)
        pixmap = QPixmap::grabWindow(scene()->views().at(0)->effectiveWinId());
}

void MSnapshotItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
        QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    painter->drawPixmap(0,0, pixmap);
}
<commit_msg>Fixes: Rotation animation freezes meegotouch rendering on Mac.<commit_after>#include "msnapshotitem.h"

#include <QGraphicsScene>
#include <QImage>
#include <QPainter>
#include <QApplication>
#include <QGraphicsView>

MSnapshotItem::MSnapshotItem(const QRectF &sceneTargetRect, QGraphicsItem *parent)
    : QGraphicsObject(parent), m_boundingRect(sceneTargetRect)
{
}

MSnapshotItem::~MSnapshotItem()
{
}

QRectF MSnapshotItem::boundingRect() const
{
    return m_boundingRect;
}

void MSnapshotItem::updateSnapshot()
{
    if (scene() && scene()->views().count() > 0)
#if defined(Q_WS_MAC) || defined(Q_WS_WIN)
        pixmap = QPixmap::grabWidget(scene()->views().at(0));
#else
        pixmap = QPixmap::grabWindow(scene()->views().at(0)->effectiveWinId());
#endif
}

void MSnapshotItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
        QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    painter->drawPixmap(0,0, pixmap);
}
<|endoftext|>


<commit_before>/**
 * @file metaCache.cc
 * @author Rafal Slota
 * @copyright (C) 2013 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in 'LICENSE.txt'
 */

#include "metaCache.h"
#include "jobScheduler.h"
#include "veilfs.h"
#include "config.h"

#include "glog/logging.h"

#include <memory.h>

using namespace std;
using boost::unordered_map;

namespace veil {
namespace client {

MetaCache::MetaCache()
{
}

MetaCache::~MetaCache()
{
}

void MetaCache::addAttr(string path, struct stat &attr)
{
    if(!VeilFS::getConfig()->getBool(ENABLE_ATTR_CACHE_OPT))
        return;

    AutoLock lock(m_statMapLock, WRITE_LOCK);
    bool wasBefore = getAttr(path, NULL);
    m_statMap[path] = make_pair(time(NULL), attr);

    if(!wasBefore)
    {
        int expiration_time = VeilFS::getConfig()->getInt(ATTR_CACHE_EXPIRATION_TIME_OPT);
        if(expiration_time <= 0)
            expiration_time = ATTR_DEFAULT_EXPIRATION_TIME;
        // because of random part, only small parts of cache will be updated at the same moment
        int when = time(NULL) + expiration_time / 2 + rand() % expiration_time;
        VeilFS::getScheduler()->addTask(Job(when, shared_from_this(), TASK_CLEAR_FILE_ATTR, path));
    }
}

bool MetaCache::getAttr(string path, struct stat* attr)
{
    AutoLock lock(m_statMapLock, READ_LOCK);
    unordered_map<string, pair<time_t, struct stat> >::iterator it = m_statMap.find(path);
    if(it == m_statMap.end())
        return false;

    if(attr != NULL) // NULL pointer is allowed to be used as parameter
        memcpy(attr, &(*it).second.second, sizeof(struct stat));

    LOG(INFO) << "Return attr with times: " << attr->st_atime << " " << attr->st_mtime << " " << st_ctime;

    return true;
}

void MetaCache::clearAttrs()
{
    AutoLock lock(m_statMapLock, WRITE_LOCK);
    m_statMap.clear();
}

void MetaCache::clearAttr(string path)
{
    AutoLock lock(m_statMapLock, WRITE_LOCK);
    LOG(INFO) << "delete attrs from cache for file: " << path;
    unordered_map<string, pair<time_t, struct stat> >::iterator it = m_statMap.find(path);
    if(it != m_statMap.end())
        m_statMap.erase(it);
}

bool MetaCache::updateTimes(string path, time_t atime, time_t mtime, time_t ctime)
{
    struct stat attr;
    if(!getAttr(path, &attr))
        return false;

    LOG(INFO) << "Set times to: " << atime << " " << mtime << " " << ctime ;

    if(atime)
        attr.st_atime = atime;
    if(mtime)
        attr.st_atime = mtime;
    if(ctime)
        attr.st_ctime = ctime;

    addAttr(path, attr);

    return true;
}

bool MetaCache::updateSize(string path, size_t size)
{
    AutoLock lock(m_statMapLock, WRITE_LOCK);
    unordered_map<string, pair<time_t, struct stat> >::iterator it = m_statMap.find(path);
    if(it == m_statMap.end())
        return false;

    it->second.second.st_size = size;

    return true;
}

bool MetaCache::runTask(TaskID taskId, string arg0, string arg1, string arg3)
{
    switch(taskId)
    {
    case TASK_CLEAR_FILE_ATTR:
        clearAttr(arg0);
        return true;
    default:
        return false;
    }
}

} // namespace client
} // namespace veil
<commit_msg>VFS-361: update cached access times right away after file open<commit_after>/**
 * @file metaCache.cc
 * @author Rafal Slota
 * @copyright (C) 2013 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in 'LICENSE.txt'
 */

#include "metaCache.h"
#include "jobScheduler.h"
#include "veilfs.h"
#include "config.h"

#include "glog/logging.h"

#include <memory.h>

using namespace std;
using boost::unordered_map;

namespace veil {
namespace client {

MetaCache::MetaCache()
{
}

MetaCache::~MetaCache()
{
}

void MetaCache::addAttr(string path, struct stat &attr)
{
    if(!VeilFS::getConfig()->getBool(ENABLE_ATTR_CACHE_OPT))
        return;

    AutoLock lock(m_statMapLock, WRITE_LOCK);
    bool wasBefore = getAttr(path, NULL);
    m_statMap[path] = make_pair(time(NULL), attr);

    if(!wasBefore)
    {
        int expiration_time = VeilFS::getConfig()->getInt(ATTR_CACHE_EXPIRATION_TIME_OPT);
        if(expiration_time <= 0)
            expiration_time = ATTR_DEFAULT_EXPIRATION_TIME;
        // because of random part, only small parts of cache will be updated at the same moment
        int when = time(NULL) + expiration_time / 2 + rand() % expiration_time;
        VeilFS::getScheduler()->addTask(Job(when, shared_from_this(), TASK_CLEAR_FILE_ATTR, path));
    }
}

bool MetaCache::getAttr(string path, struct stat* attr)
{
    AutoLock lock(m_statMapLock, READ_LOCK);
    unordered_map<string, pair<time_t, struct stat> >::iterator it = m_statMap.find(path);
    if(it == m_statMap.end())
        return false;

    if(attr != NULL) // NULL pointer is allowed to be used as parameter
        memcpy(attr, &(*it).second.second, sizeof(struct stat));

    LOG(INFO) << "Return attr with times: " << attr->st_atime << " " << attr->st_mtime << " " << attr->st_ctime;

    return true;
}

void MetaCache::clearAttrs()
{
    AutoLock lock(m_statMapLock, WRITE_LOCK);
    m_statMap.clear();
}

void MetaCache::clearAttr(string path)
{
    AutoLock lock(m_statMapLock, WRITE_LOCK);
    LOG(INFO) << "delete attrs from cache for file: " << path;
    unordered_map<string, pair<time_t, struct stat> >::iterator it = m_statMap.find(path);
    if(it != m_statMap.end())
        m_statMap.erase(it);
}

bool MetaCache::updateTimes(string path, time_t atime, time_t mtime, time_t ctime)
{
    struct stat attr;
    if(!getAttr(path, &attr))
        return false;

    LOG(INFO) << "Set times to: " << atime << " " << mtime << " " << ctime ;

    if(atime)
        attr.st_atime = atime;
    if(mtime)
        attr.st_atime = mtime;
    if(ctime)
        attr.st_ctime = ctime;

    addAttr(path, attr);

    return true;
}

bool MetaCache::updateSize(string path, size_t size)
{
    AutoLock lock(m_statMapLock, WRITE_LOCK);
    unordered_map<string, pair<time_t, struct stat> >::iterator it = m_statMap.find(path);
    if(it == m_statMap.end())
        return false;

    it->second.second.st_size = size;

    return true;
}

bool MetaCache::runTask(TaskID taskId, string arg0, string arg1, string arg3)
{
    switch(taskId)
    {
    case TASK_CLEAR_FILE_ATTR:
        clearAttr(arg0);
        return true;
    default:
        return false;
    }
}

} // namespace client
} // namespace veil
<|endoftext|>


<commit_before>// Optimize a simple optimization problem with an optimal solution
// of (1/3,1/3)

#include "optizelle/optizelle.h"
#include "optizelle/vspaces.h"
#include "optizelle/json.h"
#include <iostream>
#include <iomanip>
#include <cstdlib>

// Squares its input
template <typename Real>
Real sq(Real x){
    return x*x;
}

// Define a simple objective where
//
// f(x,y)=(x+1)^2+(y+1)^2
//
struct MyObj
    : public Optizelle::ScalarValuedFunction <double,Optizelle::Rm>
{
    typedef Optizelle::Rm <double> X;

    // Evaluation
    double operator () (const X::Vector& x) const {
        return sq(x[0]+1.)+sq(x[1]+1.);
    }

    // Gradient
    void grad(
        const X::Vector& x,
        X::Vector& grad
    ) const {
        grad[0]=2.*x[0]+2.;
        grad[1]=2.*x[1]+2.;
    }

    // Hessian-vector product
    void hessvec(
        const X::Vector& x,
        const X::Vector& dx,
        X::Vector& H_dx
    ) const {
        H_dx[0]=2.*dx[0];
        H_dx[1]=2.*dx[1];
    }
};

// Define simple inequalities
//
// h(x,y)= [ x + 2y >= 1 ]
//         [ 2x + y >= 1 ]
//
struct MyIneq
    :public Optizelle::VectorValuedFunction<double,Optizelle::Rm,Optizelle::Rm>
{
    typedef Optizelle::Rm <double> X;
    typedef Optizelle::Rm <double> Y;

    // y=h(x)
    void operator () (
        const X::Vector& x,
        Y::Vector& y
    ) const {
        y[0]=x[0]+2.*x[1]-1.;
        y[1]=2.*x[0]+x[1]-1.;
    }

    // y=h'(x)dx
    void p(
        const X::Vector& x,
        const X::Vector& dx,
        Y::Vector& y
    ) const {
        y[0]= dx[0]+2.*dx[1];
        y[1]= 2.*dx[0]+dx[1];
    }

    // z=h'(x)*dy
    void ps(
        const X::Vector& x,
        const Y::Vector& dy,
        X::Vector& z
    ) const {
        z[0]= dy[0]+2.*dy[1];
        z[1]= 2.*dy[0]+dy[1];
    }

    // z=(h''(x)dx)*dy
    void pps(
        const X::Vector& x,
        const X::Vector& dx,
        const Y::Vector& dy,
        X::Vector& z
    ) const {
        X::zero(z);
    }
};

int main(int argc,char* argv[]){
    // Read in the name for the input file
    if(argc!=2) {
        std::cerr << "rosenbrock <parameters>" << std::endl;
        exit(EXIT_FAILURE);
    }
    std::string fname(argv[1]);

    // Create a type shortcut
    using Optizelle::Rm;

    // Generate an initial guess
    std::vector <double> x(2);
    x[0]=2.1; x[1]=1.1;

    // Allocate memory for the inequality multipler
    std::vector <double> z(2);

    // Create an optimization state
    Optizelle::InequalityConstrained <double,Rm,Rm>::State::t
        state(x,z);

    // Read the parameters from file
    Optizelle::json::InequalityConstrained <double,Optizelle::Rm,Optizelle::Rm>
        ::read(Optizelle::Messaging(),fname,state);

    // Create a bundle of functions
    Optizelle::InequalityConstrained <double,Rm,Rm>::Functions::t fns;
    fns.f.reset(new MyObj);
    fns.h.reset(new MyIneq);

    // Solve the optimization problem
    Optizelle::InequalityConstrained <double,Rm,Rm>::Algorithms
        ::getMin(Optizelle::Messaging(),fns,state);

    // Print out the reason for convergence
    std::cout << "The algorithm converged due to: " <<
        Optizelle::StoppingCondition::to_string(state.opt_stop) <<
        std::endl;

    // Print out the final answer
    const std::vector <double>& opt_x=*(state.x.begin());
    std::cout << std::scientific << std::setprecision(16)
        << "The optimal point is: (" << opt_x[0] << ','
	<< opt_x[1] << ')' << std::endl;

    // Write out the final answer to file
    Optizelle::json::InequalityConstrained<double,Rm,Rm>
        ::write_restart(Optizelle::Messaging(),"solution.json",state);

    // Return that the program exited properly
    return EXIT_SUCCESS;
}
<commit_msg>I corrected a mistake in an error message.<commit_after>// Optimize a simple optimization problem with an optimal solution
// of (1/3,1/3)

#include "optizelle/optizelle.h"
#include "optizelle/vspaces.h"
#include "optizelle/json.h"
#include <iostream>
#include <iomanip>
#include <cstdlib>

// Squares its input
template <typename Real>
Real sq(Real x){
    return x*x;
}

// Define a simple objective where
//
// f(x,y)=(x+1)^2+(y+1)^2
//
struct MyObj
    : public Optizelle::ScalarValuedFunction <double,Optizelle::Rm>
{
    typedef Optizelle::Rm <double> X;

    // Evaluation
    double operator () (const X::Vector& x) const {
        return sq(x[0]+1.)+sq(x[1]+1.);
    }

    // Gradient
    void grad(
        const X::Vector& x,
        X::Vector& grad
    ) const {
        grad[0]=2.*x[0]+2.;
        grad[1]=2.*x[1]+2.;
    }

    // Hessian-vector product
    void hessvec(
        const X::Vector& x,
        const X::Vector& dx,
        X::Vector& H_dx
    ) const {
        H_dx[0]=2.*dx[0];
        H_dx[1]=2.*dx[1];
    }
};

// Define simple inequalities
//
// h(x,y)= [ x + 2y >= 1 ]
//         [ 2x + y >= 1 ]
//
struct MyIneq
    :public Optizelle::VectorValuedFunction<double,Optizelle::Rm,Optizelle::Rm>
{
    typedef Optizelle::Rm <double> X;
    typedef Optizelle::Rm <double> Y;

    // y=h(x)
    void operator () (
        const X::Vector& x,
        Y::Vector& y
    ) const {
        y[0]=x[0]+2.*x[1]-1.;
        y[1]=2.*x[0]+x[1]-1.;
    }

    // y=h'(x)dx
    void p(
        const X::Vector& x,
        const X::Vector& dx,
        Y::Vector& y
    ) const {
        y[0]= dx[0]+2.*dx[1];
        y[1]= 2.*dx[0]+dx[1];
    }

    // z=h'(x)*dy
    void ps(
        const X::Vector& x,
        const Y::Vector& dy,
        X::Vector& z
    ) const {
        z[0]= dy[0]+2.*dy[1];
        z[1]= 2.*dy[0]+dy[1];
    }

    // z=(h''(x)dx)*dy
    void pps(
        const X::Vector& x,
        const X::Vector& dx,
        const Y::Vector& dy,
        X::Vector& z
    ) const {
        X::zero(z);
    }
};

int main(int argc,char* argv[]){
    // Read in the name for the input file
    if(argc!=2) {
        std::cerr << "simple_inequality <parameters>" << std::endl;
        exit(EXIT_FAILURE);
    }
    std::string fname(argv[1]);

    // Create a type shortcut
    using Optizelle::Rm;

    // Generate an initial guess
    std::vector <double> x(2);
    x[0]=2.1; x[1]=1.1;

    // Allocate memory for the inequality multipler
    std::vector <double> z(2);

    // Create an optimization state
    Optizelle::InequalityConstrained <double,Rm,Rm>::State::t
        state(x,z);

    // Read the parameters from file
    Optizelle::json::InequalityConstrained <double,Optizelle::Rm,Optizelle::Rm>
        ::read(Optizelle::Messaging(),fname,state);

    // Create a bundle of functions
    Optizelle::InequalityConstrained <double,Rm,Rm>::Functions::t fns;
    fns.f.reset(new MyObj);
    fns.h.reset(new MyIneq);

    // Solve the optimization problem
    Optizelle::InequalityConstrained <double,Rm,Rm>::Algorithms
        ::getMin(Optizelle::Messaging(),fns,state);

    // Print out the reason for convergence
    std::cout << "The algorithm converged due to: " <<
        Optizelle::StoppingCondition::to_string(state.opt_stop) <<
        std::endl;

    // Print out the final answer
    const std::vector <double>& opt_x=*(state.x.begin());
    std::cout << std::scientific << std::setprecision(16)
        << "The optimal point is: (" << opt_x[0] << ','
	<< opt_x[1] << ')' << std::endl;

    // Write out the final answer to file
    Optizelle::json::InequalityConstrained<double,Rm,Rm>
        ::write_restart(Optizelle::Messaging(),"solution.json",state);

    // Return that the program exited properly
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "WebRequest.hpp"

namespace mobagen {
  WebRequest::WebRequest() {
#ifndef EMSCRIPTEN
#ifdef USE_CURL

#endif
#else
#endif
  }

  void WebRequest::AddHeader(const std::string &key, const std::string &value) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_header[key] = value;
#endif
#else
#endif
  }

  void WebRequest::SetAuth(const std::string &username, const std::string &password) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_session.SetAuth(cpr::Authentication(username, password));
#endif
#else
#endif
  }

  void WebRequest::SetUrl(const std::string &url) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_session.SetUrl(url);
#endif
#else
#endif
  }

  void WebRequest::SetBody(const std::string &body) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_session.SetBody(cpr::Body(body));
#endif
#else
#endif
  }

  void WebRequest::AddParameter(const std::string &key, const std::string &value) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_parameters.AddParameter(cpr::Parameter(key, value));
#endif
#else
#endif
  }

  void WebRequest::AddMultiPart(const std::string &name, const std::string &value, const std::string &content_type) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_multipart.parts.emplace_back(cpr::Part(name, value, content_type));
#endif
#else
#endif
  }

  void WebRequest::AddMultiPart(const std::string &name, const std::int32_t &value, const std::string &content_type) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_multipart.parts.emplace_back(cpr::Part(name, value, content_type));
#endif
#else
#endif
  }

  void WebRequest::AddMultiPart(const std::string &name, const std::string &filename, const std::string &data,
                                const std::string &content_type) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_multipart.parts.emplace_back(cpr::Part(name, cpr::Buffer(data.begin(), data.end(), filename), content_type));
#endif
#else
#endif
  }

  void WebRequest::SetCookies(const std::string &key, const std::string &value) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_cookies[key] = value;
#endif
#else
#endif
  }

  void WebRequest::SetDigest(const std::string &username, const std::string &password) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_session.SetDigest(cpr::Digest(username, password));
#endif
#else
#endif
  }

  void WebRequest::AddPayload(const std::string &key, const std::string &value) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_payload.AddPair(cpr::Pair(key, value));
#endif
#else
#endif
  }

  WebResponse WebRequest::Post() {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    if (m_cookies.GetEncoded().length() != 0)
      m_session.SetCookies(m_cookies);

    if (!m_header.empty())
      m_session.SetHeader(m_header);

    if (!m_parameters.content.empty())
      m_session.SetParameters(m_parameters);

    if (!m_payload.content.empty())
      m_session.SetPayload(m_payload);

    if (m_multipart.parts.size() != 0)
      m_session.SetMultipart(m_multipart);

    // response
    auto resp = m_session.Post();
    //for (auto &it : resp.header) m_response.header[it.first] = it.second;
    //for (auto &it : resp.cookies) m_response.cookies[it.first] = it.second;
    m_response.elapsed = resp.elapsed;
    m_response.error = (WebErrorCode) (int) resp.error.code;
    m_response.status_code = resp.status_code;
    m_response.text = resp.text;
    m_response.url = resp.url;
    return m_response;
#endif
#else
    return WebResponse();
#endif
  }
}
<commit_msg>fixing build for windows<commit_after>#include "WebRequest.hpp"

namespace mobagen {
  WebRequest::WebRequest() {
#ifndef EMSCRIPTEN
#ifdef USE_CURL

#endif
#else
#endif
  }

  void WebRequest::AddHeader(const std::string &key, const std::string &value) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_header[key] = value;
#endif
#else
#endif
  }

  void WebRequest::SetAuth(const std::string &username, const std::string &password) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_session.SetAuth(cpr::Authentication(username, password));
#endif
#else
#endif
  }

  void WebRequest::SetUrl(const std::string &url) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_session.SetUrl(url);
#endif
#else
#endif
  }

  void WebRequest::SetBody(const std::string &body) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_session.SetBody(cpr::Body(body));
#endif
#else
#endif
  }

  void WebRequest::AddParameter(const std::string &key, const std::string &value) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_parameters.AddParameter(cpr::Parameter(key, value));
#endif
#else
#endif
  }

  void WebRequest::AddMultiPart(const std::string &name, const std::string &value, const std::string &content_type) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_multipart.parts.emplace_back(cpr::Part(name, value, content_type));
#endif
#else
#endif
  }

  void WebRequest::AddMultiPart(const std::string &name, const std::int32_t &value, const std::string &content_type) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_multipart.parts.emplace_back(cpr::Part(name, value, content_type));
#endif
#else
#endif
  }

  void WebRequest::AddMultiPart(const std::string &name, const std::string &filename, const std::string &data,
                                const std::string &content_type) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_multipart.parts.emplace_back(cpr::Part(name, cpr::Buffer(data.begin(), data.end(), filename), content_type));
#endif
#else
#endif
  }

  void WebRequest::SetCookies(const std::string &key, const std::string &value) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_cookies[key] = value;
#endif
#else
#endif
  }

  void WebRequest::SetDigest(const std::string &username, const std::string &password) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_session.SetDigest(cpr::Digest(username, password));
#endif
#else
#endif
  }

  void WebRequest::AddPayload(const std::string &key, const std::string &value) {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    m_payload.AddPair(cpr::Pair(key, value));
#endif
#else
#endif
  }

  WebResponse WebRequest::Post() {
#ifndef EMSCRIPTEN
#ifdef USE_CURL
    if (m_cookies.GetEncoded().length() != 0)
      m_session.SetCookies(m_cookies);

    if (!m_header.empty())
      m_session.SetHeader(m_header);

    if (!m_parameters.content.empty())
      m_session.SetParameters(m_parameters);

    if (!m_payload.content.empty())
      m_session.SetPayload(m_payload);

    if (m_multipart.parts.size() != 0)
      m_session.SetMultipart(m_multipart);

    // response
    auto resp = m_session.Post();
    //for (auto &it : resp.header) m_response.header[it.first] = it.second;
    //for (auto &it : resp.cookies) m_response.cookies[it.first] = it.second;
    m_response.elapsed = resp.elapsed;
    m_response.error = (WebErrorCode) (int) resp.error.code;
    m_response.status_code = resp.status_code;
    m_response.text = resp.text;
    m_response.url = resp.url;
    return m_response;
#endif
#endif
    return WebResponse();
  }
}
<|endoftext|>


<commit_before>/**
 * v8cgi - apache module.
 * Extends v8cgi_App by adding customized initialization and (std)IO routines
 */
#include <stdlib.h>
#include <string.h>

#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "util_script.h"
#include "apr_pools.h"

#include "apr_base64.h"
#include "apr_strings.h"

#include "js_app.h"
#include "js_path.h"
#include "js_macros.h"

typedef struct {
	const char * config;
} v8cgi_config;

/**
 * First module declaration
 */
extern "C" module AP_MODULE_DECLARE_DATA v8cgi_module;

class v8cgi_Module : public v8cgi_App {
public:
	size_t reader(char * destination, size_t amount) {
		return (size_t) ap_get_client_block(this->request, destination, amount);
	}

	size_t writer(const char * data, size_t amount) {
		if (this->output_started) {
			/* response data */
			return (size_t) ap_rwrite(data, amount, this->request);
		} else {
			/* header or content separator */
			char * end = strchr((char *) data, '\r');
			if (!end) { end = strchr((char *) data, '\n'); }
			/* header or separator must end with a newline */
			if (!end) { return 0; }

			if (end == data) {
				/* content separator */
				this->output_started = true;
				return 0;
			} else {
				/* header */
				char * colon = strchr((char *) data, ':');
				/* header without colon is a bad header */
				if (!colon) { return 0; }
				size_t namelen = colon - data;

				/* skip space after colon */
				if ((size_t) (colon-data+1) < amount && *(colon+1) == ' ') { colon++; }

				size_t valuelen = end - colon - 1;
				char * name = (char *) apr_palloc(request->pool, namelen + 1);
				char * value = (char *) apr_palloc(request->pool, valuelen + 1);
				name[namelen] = '\0';
				value[valuelen] = '\0';
				strncpy(name, data, namelen);
				strncpy(value, colon+1, valuelen);

				this->header(name, value);
				return (size_t) amount;
			}
		}
	}

	/**
	 * We log errors to apache errorlog
	 */
	void error(const char * data, const char * file, int line) {
		ap_log_rerror(file, line, APLOG_ERR, 0, this->request, "%s", data);
	}

	/**
	 * Remember apache request structure and continue as usually
	 */
	int execute(request_rec * request, char ** envp) {
		this->output_started = false;
		this->request = request;
		this->mainfile = std::string(request->filename);
		path_chdir(path_dirname(this->mainfile));
		return v8cgi_App::execute(envp);
	}

	void init(v8cgi_config * cfg) {
		v8cgi_App::init();
		this->cfgfile = cfg->config;
	}

private:
	request_rec * request;
	bool output_started;

	const char * instanceType() {
		return "module";
	}

	const char * executableName() {
		return "?";
	}

	/**
	 * Set a HTTP response header
	 * @param {char *} name
	 * @param {char *} value
	 */
	void header(const char * name, const char * value) {
		if (strcasecmp(name, "content-type") == 0) {
			char * ct =  (char *) apr_palloc(request->pool, strlen(value)+1);
			strcpy(ct, value);
			this->request->content_type = ct;
		} else if (strcasecmp(name, "status") == 0) {
			char * line = (char *) apr_palloc(request->pool, strlen(value)+1);
			strcpy(line, value);
			this->request->status_line = line;
			this->request->status = atoi(value);
		} else {
			apr_table_addn(this->request->headers_out, name, value);
		}
	}
};

static v8cgi_Module app;

/**
 * This is called from Apache every time request arrives
 */
static int mod_v8cgi_handler(request_rec *r) {
	const apr_array_header_t *arr;
	const apr_table_entry_t *elts;

	if (!r->handler || strcmp(r->handler, "v8cgi-script")) { return DECLINED; }

	ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
	ap_add_common_vars(r);
	ap_add_cgi_vars(r);

    if (r->headers_in) {
		const char *auth;
		auth = apr_table_get(r->headers_in, "Authorization");
		if (auth && auth[0] != 0 && strncmp(auth, "Basic ", 6) == 0) {

		    char *user = NULL;
		    char *pass = NULL;
		    int length;

	    	user = (char *)apr_palloc(r->pool, apr_base64_decode_len(auth+6) + 1);
	    	length = apr_base64_decode(user, auth + 6);

	    	/* Null-terminate the string. */
	    	user[length] = '\0';

		    if (user) {
				pass = strchr(user, ':');
				if (pass) {
				    *pass++ = '\0';

				    apr_table_setn(r->subprocess_env, "AUTH_USER", user);
				    apr_table_setn(r->subprocess_env, "AUTH_PW", pass);
				}
		    }
		}
    }

	/* extract the CGI environment  */
	arr = apr_table_elts(r->subprocess_env);
	elts = (const apr_table_entry_t*) arr->elts;

	char ** envp = new char *[arr->nelts + 1];
	envp[arr->nelts] = NULL;

	size_t size = 0;
	size_t len1 = 0;
	size_t len2 = 0;
	for (int i=0;i<arr->nelts;i++) {
		len1 = strlen(elts[i].key);
		len2 = strlen(elts[i].val);
		size = len1 + len2 + 2;

		envp[i] = new char[size];
		envp[i][size-1] = '\0';
		envp[i][len1] = '=';

		strncpy(envp[i], elts[i].key, len1);
		strncpy(&(envp[i][len1+1]), elts[i].val, len2);
	}

	app.execute(r, envp);

	for (int i=0;i<arr->nelts;i++) {
		free(envp[i]);
	}
	free(envp);

//  Ok is safer, because HTTP_INTERNAL_SERVER_ERROR overwrites any content already generated
//	if (result) {
//		return HTTP_INTERNAL_SERVER_ERROR;
//	} else {
		return OK;
//	}
}

/**
 * Module initialization
 */
static int mod_v8cgi_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) {
	ap_add_version_component(p, "mod_v8cgi");
	v8cgi_config * cfg = (v8cgi_config *) ap_get_module_config(s->module_config, &v8cgi_module);
	app.init(cfg);
    return OK;
}

/**
 * Child initialization
 * FIXME: what is this for?
 */
static void mod_v8cgi_child_init(apr_pool_t *p, server_rec *s) {
}

/**
 * Register relevant hooks
 */
static void mod_v8cgi_register_hooks(apr_pool_t *p ) {
	ap_hook_handler(mod_v8cgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
	ap_hook_post_config(mod_v8cgi_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
	ap_hook_child_init(mod_v8cgi_child_init, NULL, NULL, APR_HOOK_MIDDLE);
}

/**
 * Create initial configuration values
 */
static void * mod_v8cgi_create_config(apr_pool_t *p, server_rec *s) {
	v8cgi_config * newcfg = (v8cgi_config *) apr_pcalloc(p, sizeof(v8cgi_config));
	newcfg->config = STRING(CONFIG_PATH);
	return (void *) newcfg;
}

/**
 * Callback executed for every configuration change
 */
static const char * set_v8cgi_config(cmd_parms * parms, void * mconfig, const char * arg) {
	v8cgi_config * cfg = (v8cgi_config *) ap_get_module_config(parms->server->module_config, &v8cgi_module);
	cfg->config = (char *) arg;
	return NULL;
}

typedef const char * (* CONFIG_HANDLER) ();
/* list of configurations */
static const command_rec mod_v8cgi_cmds[] = {
	AP_INIT_TAKE1(
		"v8cgi_Config",
		(CONFIG_HANDLER) set_v8cgi_config,
		NULL,
		RSRC_CONF,
		"Path to v8cgi configuration file."
	),
	{NULL}
};

/**
 * Module (re-)declaration
 */
extern "C" {
	module AP_MODULE_DECLARE_DATA v8cgi_module = {
		STANDARD20_MODULE_STUFF,
		NULL,
		NULL,
		mod_v8cgi_create_config,
		NULL,
		mod_v8cgi_cmds,
		mod_v8cgi_register_hooks,
	};
}
<commit_msg>#47 memory leak caused by improper memory releasing, thanks to neocoder<commit_after>/**
 * v8cgi - apache module.
 * Extends v8cgi_App by adding customized initialization and (std)IO routines
 */
#include <stdlib.h>
#include <string.h>

#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "util_script.h"
#include "apr_pools.h"

#include "apr_base64.h"
#include "apr_strings.h"

#include "js_app.h"
#include "js_path.h"
#include "js_macros.h"

typedef struct {
	const char * config;
} v8cgi_config;

/**
 * First module declaration
 */
extern "C" module AP_MODULE_DECLARE_DATA v8cgi_module;

class v8cgi_Module : public v8cgi_App {
public:
	size_t reader(char * destination, size_t amount) {
		return (size_t) ap_get_client_block(this->request, destination, amount);
	}

	size_t writer(const char * data, size_t amount) {
		if (this->output_started) {
			/* response data */
			return (size_t) ap_rwrite(data, amount, this->request);
		} else {
			/* header or content separator */
			char * end = strchr((char *) data, '\r');
			if (!end) { end = strchr((char *) data, '\n'); }
			/* header or separator must end with a newline */
			if (!end) { return 0; }

			if (end == data) {
				/* content separator */
				this->output_started = true;
				return 0;
			} else {
				/* header */
				char * colon = strchr((char *) data, ':');
				/* header without colon is a bad header */
				if (!colon) { return 0; }
				size_t namelen = colon - data;

				/* skip space after colon */
				if ((size_t) (colon-data+1) < amount && *(colon+1) == ' ') { colon++; }

				size_t valuelen = end - colon - 1;
				char * name = (char *) apr_palloc(request->pool, namelen + 1);
				char * value = (char *) apr_palloc(request->pool, valuelen + 1);
				name[namelen] = '\0';
				value[valuelen] = '\0';
				strncpy(name, data, namelen);
				strncpy(value, colon+1, valuelen);

				this->header(name, value);
				return (size_t) amount;
			}
		}
	}

	/**
	 * We log errors to apache errorlog
	 */
	void error(const char * data, const char * file, int line) {
		ap_log_rerror(file, line, APLOG_ERR, 0, this->request, "%s", data);
	}

	/**
	 * Remember apache request structure and continue as usually
	 */
	int execute(request_rec * request, char ** envp) {
		this->output_started = false;
		this->request = request;
		this->mainfile = std::string(request->filename);
		path_chdir(path_dirname(this->mainfile));
		return v8cgi_App::execute(envp);
	}

	void init(v8cgi_config * cfg) {
		v8cgi_App::init();
		this->cfgfile = cfg->config;
	}

private:
	request_rec * request;
	bool output_started;

	const char * instanceType() {
		return "module";
	}

	const char * executableName() {
		return "?";
	}

	/**
	 * Set a HTTP response header
	 * @param {char *} name
	 * @param {char *} value
	 */
	void header(const char * name, const char * value) {
		if (strcasecmp(name, "content-type") == 0) {
			char * ct =  (char *) apr_palloc(request->pool, strlen(value)+1);
			strcpy(ct, value);
			this->request->content_type = ct;
		} else if (strcasecmp(name, "status") == 0) {
			char * line = (char *) apr_palloc(request->pool, strlen(value)+1);
			strcpy(line, value);
			this->request->status_line = line;
			this->request->status = atoi(value);
		} else {
			apr_table_addn(this->request->headers_out, name, value);
		}
	}
};

static v8cgi_Module app;

/**
 * This is called from Apache every time request arrives
 */
static int mod_v8cgi_handler(request_rec *r) {
	const apr_array_header_t *arr;
	const apr_table_entry_t *elts;

	if (!r->handler || strcmp(r->handler, "v8cgi-script")) { return DECLINED; }

	ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
	ap_add_common_vars(r);
	ap_add_cgi_vars(r);

    if (r->headers_in) {
		const char *auth;
		auth = apr_table_get(r->headers_in, "Authorization");
		if (auth && auth[0] != 0 && strncmp(auth, "Basic ", 6) == 0) {

		    char *user = NULL;
		    char *pass = NULL;
		    int length;

	    	user = (char *)apr_palloc(r->pool, apr_base64_decode_len(auth+6) + 1);
	    	length = apr_base64_decode(user, auth + 6);

	    	/* Null-terminate the string. */
	    	user[length] = '\0';

		    if (user) {
				pass = strchr(user, ':');
				if (pass) {
				    *pass++ = '\0';

				    apr_table_setn(r->subprocess_env, "AUTH_USER", user);
				    apr_table_setn(r->subprocess_env, "AUTH_PW", pass);
				}
		    }
		}
    }

	/* extract the CGI environment  */
	arr = apr_table_elts(r->subprocess_env);
	elts = (const apr_table_entry_t*) arr->elts;

	char ** envp = new char *[arr->nelts + 1];
	envp[arr->nelts] = NULL;

	size_t size = 0;
	size_t len1 = 0;
	size_t len2 = 0;
	for (int i=0;i<arr->nelts;i++) {
		len1 = strlen(elts[i].key);
		len2 = strlen(elts[i].val);
		size = len1 + len2 + 2;

		envp[i] = new char[size];
		envp[i][size-1] = '\0';
		envp[i][len1] = '=';

		strncpy(envp[i], elts[i].key, len1);
		strncpy(&(envp[i][len1+1]), elts[i].val, len2);
	}

	app.execute(r, envp);

	for (int i=0;i<arr->nelts;i++) {
		delete[] envp[i];
	}
	delete[] envp;

//  Ok is safer, because HTTP_INTERNAL_SERVER_ERROR overwrites any content already generated
//	if (result) {
//		return HTTP_INTERNAL_SERVER_ERROR;
//	} else {
		return OK;
//	}
}

/**
 * Module initialization
 */
static int mod_v8cgi_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) {
	ap_add_version_component(p, "mod_v8cgi");
	v8cgi_config * cfg = (v8cgi_config *) ap_get_module_config(s->module_config, &v8cgi_module);
	app.init(cfg);
    return OK;
}

/**
 * Child initialization
 * FIXME: what is this for?
 */
static void mod_v8cgi_child_init(apr_pool_t *p, server_rec *s) {
}

/**
 * Register relevant hooks
 */
static void mod_v8cgi_register_hooks(apr_pool_t *p ) {
	ap_hook_handler(mod_v8cgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
	ap_hook_post_config(mod_v8cgi_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
	ap_hook_child_init(mod_v8cgi_child_init, NULL, NULL, APR_HOOK_MIDDLE);
}

/**
 * Create initial configuration values
 */
static void * mod_v8cgi_create_config(apr_pool_t *p, server_rec *s) {
	v8cgi_config * newcfg = (v8cgi_config *) apr_pcalloc(p, sizeof(v8cgi_config));
	newcfg->config = STRING(CONFIG_PATH);
	return (void *) newcfg;
}

/**
 * Callback executed for every configuration change
 */
static const char * set_v8cgi_config(cmd_parms * parms, void * mconfig, const char * arg) {
	v8cgi_config * cfg = (v8cgi_config *) ap_get_module_config(parms->server->module_config, &v8cgi_module);
	cfg->config = (char *) arg;
	return NULL;
}

typedef const char * (* CONFIG_HANDLER) ();
/* list of configurations */
static const command_rec mod_v8cgi_cmds[] = {
	AP_INIT_TAKE1(
		"v8cgi_Config",
		(CONFIG_HANDLER) set_v8cgi_config,
		NULL,
		RSRC_CONF,
		"Path to v8cgi configuration file."
	),
	{NULL}
};

/**
 * Module (re-)declaration
 */
extern "C" {
	module AP_MODULE_DECLARE_DATA v8cgi_module = {
		STANDARD20_MODULE_STUFF,
		NULL,
		NULL,
		mod_v8cgi_create_config,
		NULL,
		mod_v8cgi_cmds,
		mod_v8cgi_register_hooks,
	};
}
<|endoftext|>