<commit_before>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"
#include "BodyRigid.h"
#include "BodyDummy.h"
#include "Physics.h"
#include "ShapeCapsule.h"
#include "ActorBase.h"
#include "Visualizer.h"
#include "sys/SysControl.h"

using namespace MathLib;

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

/*
*/
#define ACTOR_BASE_IFPS             (1.0f / 60.0f)
#define ACTOR_BASE_CLAMP            89.9f
#define ACTOR_BASE_COLLISIONS       4

/*
*/
CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//倾斜角		二维平面坐标系中，直线向Y周延伸的方向与X轴正向之间的夹角
	m_fThetaAngle = 0.0f;			//方位角，正北方那条线与当前线条按照顺时针走过的角度

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}
	m_pDummy->SetEnabled(1);
	m_pObject->SetBody(NULL);
	m_pObject->SetBody(m_pDummy);
	m_pShape->SetBody(NULL);
	m_pShape->SetBody(m_pDummy);

	m_pObject->SetWorldTransform(Get_Body_Transform());
	m_pShape->SetRestitution(0.0f);
	m_pShape->SetCollisionMask(2);

	SetEnabled(1);
	SetViewDirection(vec3(0.0f, 1.0f, 0.0f));
	SetCollision(1);
	SetCollisionRadius(0.3f);
	SetCollisionHeight(1.0f);
	SetFriction(2.0f);
	SetMinVelocity(2.0f);
	SetMaxVelocity(4.0f);
	SetAcceleration(8.0f);
	SetDamping(8.0f);
	SetJumping(1.5f);

	SetGround(0);
	SetCeiling(0);
}

CActorBase::~CActorBase()
{
	m_pDummy->SetObject(NULL);
	delete m_pObject;
	delete m_pDummy;
}

void CActorBase::SetEnabled(int enable)
{
	m_nEnable = enable;
	m_pDummy->SetEnabled(m_nEnable);
}

int CActorBase::IsEnabled() const
{
	return m_nEnable;
}
void CActorBase::Update(float ifps)
{
	if (!m_nEnable)
	{
		return;
	}

	// impulse
	vec3 impulse = vec3_zero;

	// ortho basis
	vec3 tangent, binormal;
	OrthoBasis(m_vUp, tangent, binormal);
}<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "Engine.h"
#include "Game.h"
#include "ObjectDummy.h"
#include "BodyRigid.h"
#include "BodyDummy.h"
#include "Physics.h"
#include "ShapeCapsule.h"
#include "ActorBase.h"
#include "Visualizer.h"
#include "sys/SysControl.h"

using namespace MathLib;

#ifdef MEMORY_INFO
#define new new(__FILE__, __LINE__)
#endif // MEMORY_INFO

/*
*/
#define ACTOR_BASE_IFPS             (1.0f / 60.0f)
#define ACTOR_BASE_CLAMP            89.9f
#define ACTOR_BASE_COLLISIONS       4

/*
*/
CActorBase::CActorBase()
{
	m_vUp = vec3(0.0f, 0.0f, 1.0f);
	m_pObject = new CObjectDummy();
	m_pDummy = new CBodyDummy();
	m_pShape = new CShapeCapsule(1.0f, 1.0f);

	m_nFlush = 0;
	m_vPosition = Vec3_zero;
	m_vVelocity = Vec3_zero;
	m_fPhiAngle = 0.0f;			//倾斜角		二维平面坐标系中，直线向Y周延伸的方向与X轴正向之间的夹角
	m_fThetaAngle = 0.0f;			//方位角，正北方那条线与当前线条按照顺时针走过的角度

	for (int i = 0; i < NUM_STATES; i++)
	{
		m_pStates[i] = 0;
		m_pTimes[i] = 0.0f;
	}
	m_pDummy->SetEnabled(1);
	m_pObject->SetBody(NULL);
	m_pObject->SetBody(m_pDummy);
	m_pShape->SetBody(NULL);
	m_pShape->SetBody(m_pDummy);

	m_pObject->SetWorldTransform(Get_Body_Transform());
	m_pShape->SetRestitution(0.0f);
	m_pShape->SetCollisionMask(2);

	SetEnabled(1);
	SetViewDirection(vec3(0.0f, 1.0f, 0.0f));
	SetCollision(1);
	SetCollisionRadius(0.3f);
	SetCollisionHeight(1.0f);
	SetFriction(2.0f);
	SetMinVelocity(2.0f);
	SetMaxVelocity(4.0f);
	SetAcceleration(8.0f);
	SetDamping(8.0f);
	SetJumping(1.5f);

	SetGround(0);
	SetCeiling(0);
}

CActorBase::~CActorBase()
{
	m_pDummy->SetObject(NULL);
	delete m_pObject;
	delete m_pDummy;
}

void CActorBase::SetEnabled(int enable)
{
	m_nEnable = enable;
	m_pDummy->SetEnabled(m_nEnable);
}

int CActorBase::IsEnabled() const
{
	return m_nEnable;
}
void CActorBase::Update(float ifps)
{
	if (!m_nEnable)
	{
		return;
	}

	// impulse
	vec3 impulse = vec3_zero;

	// ortho basis
	vec3 tangent, binormal;
	OrthoBasis(m_vUp, tangent, binormal);

	// current basis
	vec3 x = quat(m_vUp, -m_fPhiAngle) * binormal;
	vec3 y = Normalize(Cross(m_vUp, x));
	vec3 z = Normalize(Cross(x, y));

}<|endoftext|>


<commit_before>/*  This file is part of the Vc library. {{{
Copyright © 2014 Matthias Kretz <kretz@kde.org>
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 names of contributing organizations 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 <COPYRIGHT HOLDER> 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 "unittest.h"
#include <list>

using Vc::simdize;
using Vc::float_v;
using Vc::int_v;
using Vc::int_m;

template <typename Scalar, typename Base, std::size_t N>
using SimdizeAdapter = Vc::SimdizeDetail::Adapter<Scalar, Base, N>;

TEST(test_simdize)
{
    using namespace std;
    using namespace Vc;
    using Test0 = simdize<float>;
    using Test1 = simdize<tuple<float, double>>;
    using Test1_0 = typename std::decay<decltype(get<0>(Test1()))>::type;
    using Test1_1 = typename tuple_element<1, typename Test1::base_type>::type;
    using Test2 = simdize<tuple<double, float>>;
    using Test2_0 = typename tuple_element<0, typename Test2::base_type>::type;
    using Test2_1 = typename tuple_element<1, typename Test2::base_type>::type;
    using Test3 = simdize<tuple<std::string, float>>;
    using Test3_1 = typename tuple_element<1, typename Test3::base_type>::type;
    using Test4 = simdize<tuple<double, std::string, float>>;
    using Test4_0 = typename tuple_element<0, typename Test4::base_type>::type;
    using Test4_1 = typename tuple_element<1, typename Test4::base_type>::type;
    using Test4_2 = typename tuple_element<2, typename Test4::base_type>::type;
    COMPARE(Test0::size(), float_v::size());
    COMPARE(Test1_0::size(), float_v::size());
    COMPARE(Test1_1::size(), float_v::size());
    COMPARE(Test1::size(), float_v::size());
    COMPARE(Test2_0::size(), double_v::size());
    COMPARE(Test2_1::size(), double_v::size());
    COMPARE(Test2::size(), double_v::size());
    COMPARE(Test3_1::size(), float_v::size());
    COMPARE(Test3::size(), float_v::size());
    COMPARE(Test4_0::size(), double_v::size());
    COMPARE(Test4_2::size(), double_v::size());
    COMPARE(Test4::size(), double_v::size());
    COMPARE(typeid(Test4_0), typeid(double_v));
    COMPARE(typeid(Test4_1), typeid(std::string));
    COMPARE(typeid(Test4_2), typeid(simdize<float, double_v::size()>));
    COMPARE(typeid(simdize<tuple<std::string>>), typeid(tuple<std::string>));
    COMPARE(typeid(simdize<float>), typeid(float_v));
    COMPARE(typeid(Test1),
            typeid(SimdizeAdapter<tuple<float, double>,
                                  tuple<float_v, simdize<double, float_v::size()>>,
                                  float_v::size()>));
}

TEST(simdize_bools)
{
    using namespace std;
    using namespace Vc;
    COMPARE(typeid(simdize<bool>), typeid(float_m));
    COMPARE(typeid(simdize<bool, float_m::size()>), typeid(float_m));
    COMPARE(typeid(simdize<bool, 0, int>), typeid(int_m));
    COMPARE(typeid(simdize<bool, int_m::size(), int>), typeid(int_m));
    COMPARE(typeid(simdize<bool, float_m::size() + 1>),
            typeid(simd_mask_array<float, float_m::size() + 1>));
    COMPARE(typeid(simdize<bool, int_m::size() + 1, int>),
            typeid(simd_mask_array<int, int_m::size() + 1>));

    COMPARE(typeid(simdize<tuple<bool>>),
            typeid(SimdizeAdapter<tuple<bool>, tuple<float_m>, float_m::size()>));
    COMPARE(typeid(simdize<tuple<bool>, float_m::size()>),
            typeid(SimdizeAdapter<tuple<bool>, tuple<float_m>, float_m::size()>));
    COMPARE(
        typeid(simdize<tuple<bool>, float_m::size() + 1>),
        typeid(
            SimdizeAdapter<tuple<bool>, tuple<simd_mask_array<float, float_m::size() + 1>>,
                           float_m::size() + 1>));

    COMPARE(typeid(simdize<tuple<int, bool>>),
            typeid(SimdizeAdapter<tuple<int, bool>, tuple<int_v, int_m>, int_v::size()>));
    COMPARE(
        typeid(simdize<tuple<int, bool>, 3>),
        typeid(SimdizeAdapter<tuple<int, bool>,
                              tuple<simdarray<int, 3>, simd_mask_array<float, 3>>, 3>));

    COMPARE(
        typeid(simdize<tuple<bool, double, bool>>),
        typeid(SimdizeAdapter<tuple<bool, double, bool>,
                              tuple<float_m, simdarray<double, float_m::size()>, float_m>,
                              float_m::size()>));
    COMPARE(typeid(simdize<tuple<bool, double, bool>, float_m::size() + 1>),
            typeid(SimdizeAdapter<tuple<bool, double, bool>,
                                  tuple<simd_mask_array<float, float_m::size() + 1>,
                                        simdarray<double, float_m::size() + 1>,
                                        simd_mask_array<float, float_m::size() + 1>>,
                                  float_m::size() + 1>));
    COMPARE(typeid(simdize<tuple<bool, double, bool>, 0, double>),
            typeid(SimdizeAdapter<tuple<bool, double, bool>,
                                  tuple<double_m, double_v, double_m>, double_m::size()>));

    COMPARE(typeid(simdize<tuple<int, double, bool>, 0, double>),
            typeid(SimdizeAdapter<tuple<int, double, bool>,
                                  tuple<int_v, simdize<double, int_v::size()>,
                                        simdize<bool, int_v::size(), double>>,
                                  int_v::size()>));
}

template <typename, int...> struct Foo1 {};
template <typename, typename, unsigned...> struct Foo2 {};
template <typename, typename, typename, std::size_t...> struct Foo3 {};

TEST(nontype_template_parameters)
{
    using namespace std;
    using namespace Vc;
    using std::array;

    static_assert(SimdizeDetail::is_class_template<array<float, 3>>::value, "");
    static_assert(SimdizeDetail::is_class_template<Foo1<float, 3, 5, 6>>::value, "");
    static_assert(SimdizeDetail::is_class_template<Foo2<int, float, 3, 5, 6>>::value, "");

    COMPARE(typeid(simdize<array<float, 3>>),
            typeid(SimdizeAdapter<array<float, 3>, array<float_v, 3>, float_v::size()>));
    COMPARE(typeid(simdize<array<bool, 3>>),
            typeid(SimdizeAdapter<array<bool, 3>, array<float_m, 3>, float_m::size()>));
    COMPARE(
        typeid(simdize<Foo1<float, 3, 5, 6>>),
        typeid(
            SimdizeAdapter<Foo1<float, 3, 5, 6>, Foo1<float_v, 3, 5, 6>, float_v::size()>));
    COMPARE(typeid(simdize<Foo2<int, float, 3, 5, 6>>),
            typeid(SimdizeAdapter<Foo2<int, float, 3, 5, 6>,
                                  Foo2<int_v, float_v, 3, 5, 6>, int_v::size()>));
    COMPARE(typeid(simdize<Foo3<int, int, float, 3, 5, 6>>),
            typeid(SimdizeAdapter<Foo3<int, int, float, 3, 5, 6>,
                                  Foo3<int_v, int_v, float_v, 3, 5, 6>, int_v::size()>));
}

TEST(tuple_interface)
{
    using V0 = simdize<std::tuple<int, bool>>;
    COMPARE(std::tuple_size<V0>::value, 2u);
    COMPARE(typeid(typename std::tuple_element<0, V0>::type), typeid(int_v));
    COMPARE(typeid(typename std::tuple_element<1, V0>::type), typeid(int_m));

    V0 v;
    COMPARE(typeid(decltype(std::get<0>(v))), typeid(int_v));
    COMPARE(typeid(decltype(std::get<1>(v))), typeid(int_m));
    std::get<0>(v) = int_v::IndexesFromZero();
    COMPARE(std::get<0>(v), int_v::IndexesFromZero());
    std::get<0>(v) += 1;
    COMPARE(std::get<0>(v), int_v::IndexesFromZero() + 1);
}

TEST(assign)
{
    using T = std::tuple<float, unsigned>;
    using V = simdize<T>;
    V v;
    for (unsigned i = 0; i < v.size(); ++i) {
        assign(v, i, T{1.f * i, i});
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
}

TEST(extract)
{
    using T = std::tuple<float, unsigned>;
    using V = simdize<T>;
    V v;
    for (unsigned i = 0; i < v.size(); ++i) {
        assign(v, i, T{1.f * i, i});
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        COMPARE(extract(v, i), T(1.f * i, i));
    }
}

TEST(decorate)
{
    using T = std::tuple<float, unsigned>;
    using V = simdize<T>;
    V v;
    auto vv = decorate(v);
    for (unsigned i = 0; i < v.size(); ++i) {
        vv[i] = T{1.f * i, i};
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        T x = vv[i];
        COMPARE(x, T(1.f * i, i));
    }
    const V &v2 = v;
    for (unsigned i = 0; i < v.size(); ++i) {
        T x = decorate(v2)[i];
        COMPARE(x, T(1.f * i, i));
    }
}

TEST(broadcast)
{
    {
        using T = std::tuple<float, int>;
        using V = simdize<T>;

        T scalar(2.f, 3);
        V vector(scalar);
        COMPARE(std::get<0>(vector), float_v(2.f));
        COMPARE(std::get<1>(vector), (simdize<int, V::size()>(3)));
    }
    {
        using T = std::array<int, 3>;
        using V = simdize<T>;
        T scalar{1, 2, 3};
        V vector(scalar);
        COMPARE(vector[0], int_v(1));
        COMPARE(vector[1], int_v(2));
        COMPARE(vector[2], int_v(3));
    }
}

TEST(list_iterator_vectorization)
{
    {
        using L = std::list<float>;
        using LIV = simdize<L::iterator>;
        L list;
        for (auto i = 1024; i; --i) {
            list.push_back(i);
        }
        LIV b = list.begin();
        LIV e = list.end();
        float_v reference = list.size() - float_v::IndexesFromZero();
        for (; b != e; ++b, reference -= float_v::size()) {
            float_v x = *b;
            COMPARE(x, reference);
            COMPARE(*b, reference);
            *b = x + 1;
            COMPARE(*b, reference + 1);
        }
        reference = list.size() - float_v::IndexesFromZero() + 1;
        for (b = list.begin(); b != e; ++b, reference -= float_v::size()) {
            float_v x = *b;
            COMPARE(x, reference);
            COMPARE(*b, reference);
        }
    }
    {
        using T = std::tuple<float, unsigned, float>;
        using V = simdize<T>;
        using L = std::list<T>;
        using LIV = simdize<L::iterator>;
        L list;
        for (auto i = 1024; i; --i) {
            list.push_back(T(i, i * 2, i * 3));
        }
        LIV b = list.begin();
        LIV e = list.end();
        auto reference1 = list.size() - float_v::IndexesFromZero();
        auto reference2 = list.size() - simdize<unsigned, V::size()>::IndexesFromZero();
        for (; b != e; ++b, reference1 -= V::size(), reference2 -= V::size()) {
            V x = *b;
            COMPARE(x, V(reference1, reference2 * 2, reference1 * 3));
            COMPARE(std::get<0>(*b), reference1);
        }
    }
}

// vim: foldmethod=marker
<commit_msg>simdize: fix bool vectorization test<commit_after>/*  This file is part of the Vc library. {{{
Copyright © 2014 Matthias Kretz <kretz@kde.org>
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 names of contributing organizations 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 <COPYRIGHT HOLDER> 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 "unittest.h"
#include <list>

using Vc::simdize;
using Vc::float_v;
using Vc::int_v;
using Vc::int_m;

template <typename Scalar, typename Base, std::size_t N>
using SimdizeAdapter = Vc::SimdizeDetail::Adapter<Scalar, Base, N>;

TEST(test_simdize)
{
    using namespace std;
    using namespace Vc;
    using Test0 = simdize<float>;
    using Test1 = simdize<tuple<float, double>>;
    using Test1_0 = typename std::decay<decltype(get<0>(Test1()))>::type;
    using Test1_1 = typename tuple_element<1, typename Test1::base_type>::type;
    using Test2 = simdize<tuple<double, float>>;
    using Test2_0 = typename tuple_element<0, typename Test2::base_type>::type;
    using Test2_1 = typename tuple_element<1, typename Test2::base_type>::type;
    using Test3 = simdize<tuple<std::string, float>>;
    using Test3_1 = typename tuple_element<1, typename Test3::base_type>::type;
    using Test4 = simdize<tuple<double, std::string, float>>;
    using Test4_0 = typename tuple_element<0, typename Test4::base_type>::type;
    using Test4_1 = typename tuple_element<1, typename Test4::base_type>::type;
    using Test4_2 = typename tuple_element<2, typename Test4::base_type>::type;
    COMPARE(Test0::size(), float_v::size());
    COMPARE(Test1_0::size(), float_v::size());
    COMPARE(Test1_1::size(), float_v::size());
    COMPARE(Test1::size(), float_v::size());
    COMPARE(Test2_0::size(), double_v::size());
    COMPARE(Test2_1::size(), double_v::size());
    COMPARE(Test2::size(), double_v::size());
    COMPARE(Test3_1::size(), float_v::size());
    COMPARE(Test3::size(), float_v::size());
    COMPARE(Test4_0::size(), double_v::size());
    COMPARE(Test4_2::size(), double_v::size());
    COMPARE(Test4::size(), double_v::size());
    COMPARE(typeid(Test4_0), typeid(double_v));
    COMPARE(typeid(Test4_1), typeid(std::string));
    COMPARE(typeid(Test4_2), typeid(simdize<float, double_v::size()>));
    COMPARE(typeid(simdize<tuple<std::string>>), typeid(tuple<std::string>));
    COMPARE(typeid(simdize<float>), typeid(float_v));
    COMPARE(typeid(Test1),
            typeid(SimdizeAdapter<tuple<float, double>,
                                  tuple<float_v, simdize<double, float_v::size()>>,
                                  float_v::size()>));
}

TEST(simdize_bools)
{
    using namespace std;
    using namespace Vc;
    COMPARE(typeid(simdize<bool>), typeid(float_m));
    COMPARE(typeid(simdize<bool, float_m::size()>), typeid(float_m));
    COMPARE(typeid(simdize<bool, 0, int>), typeid(int_m));
    COMPARE(typeid(simdize<bool, int_m::size(), int>), typeid(int_m));
    COMPARE(typeid(simdize<bool, float_m::size() + 1>),
            typeid(simd_mask_array<float, float_m::size() + 1>));
    COMPARE(typeid(simdize<bool, int_m::size() + 1, int>),
            typeid(simd_mask_array<int, int_m::size() + 1>));

    COMPARE(typeid(simdize<tuple<bool>>),
            typeid(SimdizeAdapter<tuple<bool>, tuple<float_m>, float_m::size()>));
    COMPARE(typeid(simdize<tuple<bool>, float_m::size()>),
            typeid(SimdizeAdapter<tuple<bool>, tuple<float_m>, float_m::size()>));
    COMPARE(
        typeid(simdize<tuple<bool>, float_m::size() + 1>),
        typeid(
            SimdizeAdapter<tuple<bool>, tuple<simd_mask_array<float, float_m::size() + 1>>,
                           float_m::size() + 1>));

    COMPARE(typeid(simdize<tuple<int, bool>>),
            typeid(SimdizeAdapter<tuple<int, bool>, tuple<int_v, int_m>, int_v::size()>));
    COMPARE(
        typeid(simdize<tuple<int, bool>, 3>),
        typeid(SimdizeAdapter<tuple<int, bool>,
                              tuple<simdarray<int, 3>, simd_mask_array<float, 3>>, 3>));

    COMPARE(
        typeid(simdize<tuple<bool, double, bool>>),
        typeid(SimdizeAdapter<
            tuple<bool, double, bool>,
            tuple<float_m,
                  typename std::conditional<float_m::size() == double_v::size(), double_v,
                                            simdarray<double, float_m::size()>>::type,
                  float_m>,
            float_m::size()>));
    COMPARE(typeid(simdize<tuple<bool, double, bool>, float_m::size() + 1>),
            typeid(SimdizeAdapter<tuple<bool, double, bool>,
                                  tuple<simd_mask_array<float, float_m::size() + 1>,
                                        simdarray<double, float_m::size() + 1>,
                                        simd_mask_array<float, float_m::size() + 1>>,
                                  float_m::size() + 1>));
    COMPARE(typeid(simdize<tuple<bool, double, bool>, 0, double>),
            typeid(SimdizeAdapter<tuple<bool, double, bool>,
                                  tuple<double_m, double_v, double_m>, double_m::size()>));

    COMPARE(typeid(simdize<tuple<int, double, bool>, 0, double>),
            typeid(SimdizeAdapter<tuple<int, double, bool>,
                                  tuple<int_v, simdize<double, int_v::size()>,
                                        simdize<bool, int_v::size(), double>>,
                                  int_v::size()>));
}

template <typename, int...> struct Foo1 {};
template <typename, typename, unsigned...> struct Foo2 {};
template <typename, typename, typename, std::size_t...> struct Foo3 {};

TEST(nontype_template_parameters)
{
    using namespace std;
    using namespace Vc;
    using std::array;

    static_assert(SimdizeDetail::is_class_template<array<float, 3>>::value, "");
    static_assert(SimdizeDetail::is_class_template<Foo1<float, 3, 5, 6>>::value, "");
    static_assert(SimdizeDetail::is_class_template<Foo2<int, float, 3, 5, 6>>::value, "");

    COMPARE(typeid(simdize<array<float, 3>>),
            typeid(SimdizeAdapter<array<float, 3>, array<float_v, 3>, float_v::size()>));
    COMPARE(typeid(simdize<array<bool, 3>>),
            typeid(SimdizeAdapter<array<bool, 3>, array<float_m, 3>, float_m::size()>));
    COMPARE(
        typeid(simdize<Foo1<float, 3, 5, 6>>),
        typeid(
            SimdizeAdapter<Foo1<float, 3, 5, 6>, Foo1<float_v, 3, 5, 6>, float_v::size()>));
    COMPARE(typeid(simdize<Foo2<int, float, 3, 5, 6>>),
            typeid(SimdizeAdapter<Foo2<int, float, 3, 5, 6>,
                                  Foo2<int_v, float_v, 3, 5, 6>, int_v::size()>));
    COMPARE(typeid(simdize<Foo3<int, int, float, 3, 5, 6>>),
            typeid(SimdizeAdapter<Foo3<int, int, float, 3, 5, 6>,
                                  Foo3<int_v, int_v, float_v, 3, 5, 6>, int_v::size()>));
}

TEST(tuple_interface)
{
    using V0 = simdize<std::tuple<int, bool>>;
    COMPARE(std::tuple_size<V0>::value, 2u);
    COMPARE(typeid(typename std::tuple_element<0, V0>::type), typeid(int_v));
    COMPARE(typeid(typename std::tuple_element<1, V0>::type), typeid(int_m));

    V0 v;
    COMPARE(typeid(decltype(std::get<0>(v))), typeid(int_v));
    COMPARE(typeid(decltype(std::get<1>(v))), typeid(int_m));
    std::get<0>(v) = int_v::IndexesFromZero();
    COMPARE(std::get<0>(v), int_v::IndexesFromZero());
    std::get<0>(v) += 1;
    COMPARE(std::get<0>(v), int_v::IndexesFromZero() + 1);
}

TEST(assign)
{
    using T = std::tuple<float, unsigned>;
    using V = simdize<T>;
    V v;
    for (unsigned i = 0; i < v.size(); ++i) {
        assign(v, i, T{1.f * i, i});
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
}

TEST(extract)
{
    using T = std::tuple<float, unsigned>;
    using V = simdize<T>;
    V v;
    for (unsigned i = 0; i < v.size(); ++i) {
        assign(v, i, T{1.f * i, i});
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        COMPARE(extract(v, i), T(1.f * i, i));
    }
}

TEST(decorate)
{
    using T = std::tuple<float, unsigned>;
    using V = simdize<T>;
    V v;
    auto vv = decorate(v);
    for (unsigned i = 0; i < v.size(); ++i) {
        vv[i] = T{1.f * i, i};
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        COMPARE(std::get<0>(v)[i], 1.f * i);
        COMPARE(std::get<1>(v)[i], i);
    }
    for (unsigned i = 0; i < v.size(); ++i) {
        T x = vv[i];
        COMPARE(x, T(1.f * i, i));
    }
    const V &v2 = v;
    for (unsigned i = 0; i < v.size(); ++i) {
        T x = decorate(v2)[i];
        COMPARE(x, T(1.f * i, i));
    }
}

TEST(broadcast)
{
    {
        using T = std::tuple<float, int>;
        using V = simdize<T>;

        T scalar(2.f, 3);
        V vector(scalar);
        COMPARE(std::get<0>(vector), float_v(2.f));
        COMPARE(std::get<1>(vector), (simdize<int, V::size()>(3)));
    }
    {
        using T = std::array<int, 3>;
        using V = simdize<T>;
        T scalar{1, 2, 3};
        V vector(scalar);
        COMPARE(vector[0], int_v(1));
        COMPARE(vector[1], int_v(2));
        COMPARE(vector[2], int_v(3));
    }
}

TEST(list_iterator_vectorization)
{
    {
        using L = std::list<float>;
        using LIV = simdize<L::iterator>;
        L list;
        for (auto i = 1024; i; --i) {
            list.push_back(i);
        }
        LIV b = list.begin();
        LIV e = list.end();
        float_v reference = list.size() - float_v::IndexesFromZero();
        for (; b != e; ++b, reference -= float_v::size()) {
            float_v x = *b;
            COMPARE(x, reference);
            COMPARE(*b, reference);
            *b = x + 1;
            COMPARE(*b, reference + 1);
        }
        reference = list.size() - float_v::IndexesFromZero() + 1;
        for (b = list.begin(); b != e; ++b, reference -= float_v::size()) {
            float_v x = *b;
            COMPARE(x, reference);
            COMPARE(*b, reference);
        }
    }
    {
        using T = std::tuple<float, unsigned, float>;
        using V = simdize<T>;
        using L = std::list<T>;
        using LIV = simdize<L::iterator>;
        L list;
        for (auto i = 1024; i; --i) {
            list.push_back(T(i, i * 2, i * 3));
        }
        LIV b = list.begin();
        LIV e = list.end();
        auto reference1 = list.size() - float_v::IndexesFromZero();
        auto reference2 = list.size() - simdize<unsigned, V::size()>::IndexesFromZero();
        for (; b != e; ++b, reference1 -= V::size(), reference2 -= V::size()) {
            V x = *b;
            COMPARE(x, V(reference1, reference2 * 2, reference1 * 3));
            COMPARE(std::get<0>(*b), reference1);
        }
    }
}

// vim: foldmethod=marker
<|endoftext|>


<commit_before>/*
 * Skaffari - a mail account administration web interface based on Cutelyst
 * Copyright (C) 2017 Matthias Fehring <kontakt@buschmann23.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "skaffari.h"

#include <Cutelyst/Application>
#include <Cutelyst/Plugins/StaticSimple/StaticSimple>
#include <Cutelyst/Plugins/View/Grantlee/grantleeview.h>
#include <Cutelyst/Plugins/Session/Session>
#include <Cutelyst/Plugins/Authentication/authentication.h>
#include <Cutelyst/Plugins/Authentication/credentialpassword.h>
#include <Cutelyst/Plugins/Authentication/authenticationrealm.h>
#include <Cutelyst/Plugins/Utils/Sql>
#include <Cutelyst/Plugins/StatusMessage>
#include <Cutelyst/Engine>
#include <grantlee5/grantlee/metatype.h>
#include <grantlee5/grantlee/engine.h>
#include <QSqlDatabase>
#include <QSqlError>
#include <QDir>
#include <QMetaType>
#include <QCoreApplication>
#include <QTranslator>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>

#include "objects/domain.h"
#include "objects/simpleadmin.h"
#include "objects/simpledomain.h"
#include "objects/simpleaccount.h"
#include "objects/adminaccount.h"
#include "objects/account.h"
#include "objects/folder.h"
#include "objects/helpentry.h"

#include "utils/language.h"
#include "utils/skaffariconfig.h"

#include "../common/config.h"
#include "../common/global.h"
#include "root.h"
#include "authstoresql.h"
#include "login.h"
#include "logout.h"
#include "domaineditor.h"
#include "accounteditor.h"
#include "admineditor.h"
#include "myaccount.h"
#include "settingseditor.h"

Q_LOGGING_CATEGORY(SK_CORE, "skaffari.core")

using namespace Cutelyst;

bool Skaffari::isInitialized = false;

Skaffari::Skaffari(QObject *parent) : Application(parent)
{
}

Skaffari::~Skaffari()
{
}

bool Skaffari::init()
{
    QCoreApplication::setApplicationName(QStringLiteral("Skaffari"));
    QCoreApplication::setApplicationVersion(QStringLiteral(SKAFFARI_VERSION));

    qRegisterMetaType<quota_size_t>("quota_size_t");
    qRegisterMetaType<dbid_t>("dbid_t");
    qRegisterMetaType<Folder>();
    qRegisterMetaType<Domain>();
    qRegisterMetaType<SimpleAdmin>();
    qRegisterMetaType<SimpleDomain>();
    qRegisterMetaType<SimpleAccount>();
    qRegisterMetaType<AdminAccount>();
    qRegisterMetaType<Language>();
    qRegisterMetaType<Account>();
    qRegisterMetaType<HelpEntry>();
    qRegisterMetaType<HelpHash>("HelpHash");

    Grantlee::registerMetaType<Folder>();
    Grantlee::registerMetaType<Domain>();
    Grantlee::registerMetaType<SimpleAdmin>();
    Grantlee::registerMetaType<SimpleDomain>();
    Grantlee::registerMetaType<SimpleAccount>();
    Grantlee::registerMetaType<AdminAccount>();
    Grantlee::registerMetaType<Language>();
    Grantlee::registerMetaType<Account>();
    Grantlee::registerMetaType<HelpEntry>();

    const QString tmplName = QStringLiteral("default");
    const QString tmplBasePath = QStringLiteral(SKAFFARI_TMPLDIR) + QLatin1Char('/') + tmplName;

    if (!isInitialized) {
        QVariantMap tmplConfig;
        QFile tmplConfigFile(tmplBasePath + QLatin1String("/config.json"));
        if (tmplConfigFile.exists()) {
            qCDebug(SK_CORE, "Found template configuration file.");
            if (tmplConfigFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
                QJsonParseError jpe;
                QJsonDocument tmplJsonConfig(QJsonDocument::fromJson(tmplConfigFile.readAll(), &jpe));
                if (jpe.error != QJsonParseError::NoError) {
                    qCCritical(SK_CORE, "Failed to parse template configuration file: %s", qUtf8Printable(jpe.errorString()));
                    return false;
                }

                tmplConfig = tmplJsonConfig.object().toVariantMap();
            } else {
                qCCritical(SK_CORE, "Failed to open template configuration file %s.", qUtf8Printable(tmplConfigFile.fileName()));
                return false;
            }
        }

        qCDebug(SK_CORE) << "Initializing configuration.";
        SkaffariConfig::load(engine()->config(QStringLiteral("Accounts")),
                             engine()->config(QStringLiteral("Admins")),
                             engine()->config(QStringLiteral("IMAP")),
                             tmplConfig);

        if (SkaffariConfig::imapUser().isEmpty()) {
            qCCritical(SK_CORE) << "No valid IMAP user defined.";
            return false;
        }

        if (SkaffariConfig::imapPassword().isEmpty()) {
            qCCritical(SK_CORE) << "No valid IMAP password defined.";
            return false;
        }

        // initialize DB one time to prevent https://bugreports.qt.io/browse/QTBUG-54872
        if (!initDb()) {
            return false;
        }

        SkaffariConfig::loadSettingsFromDB();

        isInitialized = true;
    }

    QString sitePath = tmplBasePath + QLatin1String("/site");

    auto view = new GrantleeView(this);
    view->setTemplateExtension(QStringLiteral(".html"));
    view->setWrapper(QStringLiteral("wrapper.html"));
	view->setCache(false);
    view->setIncludePaths({sitePath});
    view->engine()->addDefaultLibrary(QStringLiteral("grantlee_i18ntags"));
    view->engine()->addDefaultLibrary(QStringLiteral("grantlee_skaffari"));

    /* Start loading translations */
    const QString tmplTransFileName = QLatin1String("tmpl_") + tmplName;
    const QString tmplTransFilePath = tmplBasePath + QLatin1String("/l10n");

    const QStringList supportedLangs = SKAFFARI_SUPPORTED_LANGS;
    for (const QString &lang : supportedLangs) {
        if (Q_LIKELY(lang != QLatin1String("en"))) {
            qCDebug(SK_CORE, "Loading translations for language %s.", qUtf8Printable(lang));
            const QLocale locale(lang);
            if (Q_LIKELY(locale.language() != QLocale::C)) {
                auto coreTrans = new QTranslator(this);
                if (Q_LIKELY(coreTrans->load(locale, QStringLiteral("skaffari"), QStringLiteral("_"), QStringLiteral(SKAFFARI_L10NDIR)))) {
                    addTranslator(locale, coreTrans);
                } else {
                    qCWarning(SK_CORE, "Failed to load core translation file for language %s from %s.", qUtf8Printable(locale.bcp47Name()), SKAFFARI_L10NDIR);
                }

                auto tmplTrans = new QTranslator(this);
                if (Q_LIKELY(tmplTrans->load(locale, tmplTransFileName, QStringLiteral("_"), tmplTransFilePath))) {
                    view->addTranslator(locale, tmplTrans);
                } else {
                    qCWarning(SK_CORE, "Failed to load template translation file for language %s from %s.", qUtf8Printable(locale.bcp47Name()), qUtf8Printable(tmplTransFilePath));
                }
            } else {
                qCWarning(SK_CORE, "Invalid language code: %s", qUtf8Printable(lang));
            }
        }
    }
    /* End loading translations */

	new Root(this);
	new Login(this);
	new Logout(this);
	new DomainEditor(this);
	new AccountEditor(this);
    new AdminEditor(this);
    new MyAccount(this);
    new SettingsEditor(this);

    auto staticSimple = new StaticSimple(this);
    QString staticPath = tmplBasePath + QLatin1String("/static");
    staticSimple->setIncludePaths({staticPath});

	new Session(this);

    new StatusMessage(this);

    auto auth = new Authentication(this);
    auto credential = new CredentialPassword(auth);
    credential->setPasswordType(CredentialPassword::Hashed);
    auto store = new AuthStoreSql(this);
    auto realm = new AuthenticationRealm(store, credential, auth);
    store->setParent(realm);
    auth->addRealm(store, credential);

    defaultHeaders().setHeader(QStringLiteral("X-Frame-Options"), QStringLiteral("DENY"));
    defaultHeaders().setHeader(QStringLiteral("X-Content-Type-Options"), QStringLiteral("nosniff"));
    defaultHeaders().setHeader(QStringLiteral("X-XSS-Protection"), QStringLiteral("1; mode=block"));
    defaultHeaders().setHeader(QStringLiteral("Content-Security-Policy"), QStringLiteral("default-src 'none'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; connect-src 'self';"));
    defaultHeaders().setHeader(QStringLiteral("X-Robots-Tag"), QStringLiteral("none"));

    return true;
}

bool Skaffari::postFork()
{

    initDb();

    return true;
}

bool Skaffari::initDb() const
{
    const QVariantMap dbconfig = engine()->config(QStringLiteral("Database"));
    const QString dbtype = dbconfig.value(QStringLiteral("type")).toString();
    const QString dbname = dbconfig.value(QStringLiteral("name")).toString();
    const QString dbuser = dbconfig.value(QStringLiteral("user")).toString();
    const QString dbpass = dbconfig.value(QStringLiteral("password")).toString();
    const QString dbhost = dbconfig.value(QStringLiteral("host"), QStringLiteral("localhost")).toString();
    const int dbport = dbconfig.value(QStringLiteral("port"), QStringLiteral("3306")).toInt();

    qCDebug(SK_CORE) << "Establishing database connection";
    QSqlDatabase db;
    const QString dbConName = Sql::databaseNameThread();
    if (dbtype == QLatin1String("QMYSQL")) {
        if (dbname.isEmpty()) {
            qCCritical(SK_CORE) << "No database name set!";
            return false;
        }
        if (dbuser.isEmpty()) {
            qCCritical(SK_CORE) << "No database user set!";
            return false;
        }
        if (dbpass.isEmpty()) {
            qCCritical(SK_CORE) << "No database password set!";
            return false;
        }

        db = QSqlDatabase::addDatabase(dbtype, dbConName);
        if (Q_LIKELY(db.isValid())) {
            db.setDatabaseName(dbname);
            db.setUserName(dbuser);
            db.setPassword(dbpass);

            if (dbhost[0] == QLatin1Char('/')) {
                db.setConnectOptions(QStringLiteral("UNIX_SOCKET=%1;MYSQL_OPT_RECONNECT=1;CLIENT_INTERACTIVE=1").arg(dbhost));
            } else {
                db.setConnectOptions(QStringLiteral("MYSQL_OPT_RECONNECT=1;CLIENT_INTERACTIVE=1"));
                db.setHostName(dbhost);
                db.setPort(dbport);
            }
        } else {
            qCCritical(SK_CORE) << "Failed to obtain database object.";
            return false;
        }
    } else {
        qCCritical(SK_CORE) << dbtype << "is not a supported database type.";
        return false;
    }

    if (Q_UNLIKELY(!db.open())) {
        qCCritical(SK_CORE) << "Failed to establish database connection:" << db.lastError().text();
        return false;
    }

    return true;
}

#include "moc_skaffari.cpp"
<commit_msg>Skaffari core: use initializer list<commit_after>/*
 * Skaffari - a mail account administration web interface based on Cutelyst
 * Copyright (C) 2017 Matthias Fehring <kontakt@buschmann23.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "skaffari.h"

#include <Cutelyst/Application>
#include <Cutelyst/Plugins/StaticSimple/StaticSimple>
#include <Cutelyst/Plugins/View/Grantlee/grantleeview.h>
#include <Cutelyst/Plugins/Session/Session>
#include <Cutelyst/Plugins/Authentication/authentication.h>
#include <Cutelyst/Plugins/Authentication/credentialpassword.h>
#include <Cutelyst/Plugins/Authentication/authenticationrealm.h>
#include <Cutelyst/Plugins/Utils/Sql>
#include <Cutelyst/Plugins/StatusMessage>
#include <Cutelyst/Engine>
#include <grantlee5/grantlee/metatype.h>
#include <grantlee5/grantlee/engine.h>
#include <QSqlDatabase>
#include <QSqlError>
#include <QDir>
#include <QMetaType>
#include <QCoreApplication>
#include <QTranslator>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>

#include "objects/domain.h"
#include "objects/simpleadmin.h"
#include "objects/simpledomain.h"
#include "objects/simpleaccount.h"
#include "objects/adminaccount.h"
#include "objects/account.h"
#include "objects/folder.h"
#include "objects/helpentry.h"

#include "utils/language.h"
#include "utils/skaffariconfig.h"

#include "../common/config.h"
#include "../common/global.h"
#include "root.h"
#include "authstoresql.h"
#include "login.h"
#include "logout.h"
#include "domaineditor.h"
#include "accounteditor.h"
#include "admineditor.h"
#include "myaccount.h"
#include "settingseditor.h"

Q_LOGGING_CATEGORY(SK_CORE, "skaffari.core")

using namespace Cutelyst;

bool Skaffari::isInitialized = false;

Skaffari::Skaffari(QObject *parent) : Application(parent)
{
}

Skaffari::~Skaffari()
{
}

bool Skaffari::init()
{
    QCoreApplication::setApplicationName(QStringLiteral("Skaffari"));
    QCoreApplication::setApplicationVersion(QStringLiteral(SKAFFARI_VERSION));

    qRegisterMetaType<quota_size_t>("quota_size_t");
    qRegisterMetaType<dbid_t>("dbid_t");
    qRegisterMetaType<Folder>();
    qRegisterMetaType<Domain>();
    qRegisterMetaType<SimpleAdmin>();
    qRegisterMetaType<SimpleDomain>();
    qRegisterMetaType<SimpleAccount>();
    qRegisterMetaType<AdminAccount>();
    qRegisterMetaType<Language>();
    qRegisterMetaType<Account>();
    qRegisterMetaType<HelpEntry>();
    qRegisterMetaType<HelpHash>("HelpHash");

    Grantlee::registerMetaType<Folder>();
    Grantlee::registerMetaType<Domain>();
    Grantlee::registerMetaType<SimpleAdmin>();
    Grantlee::registerMetaType<SimpleDomain>();
    Grantlee::registerMetaType<SimpleAccount>();
    Grantlee::registerMetaType<AdminAccount>();
    Grantlee::registerMetaType<Language>();
    Grantlee::registerMetaType<Account>();
    Grantlee::registerMetaType<HelpEntry>();

    const QString tmplName = QStringLiteral("default");
    const QString tmplBasePath = QStringLiteral(SKAFFARI_TMPLDIR) + QLatin1Char('/') + tmplName;

    if (!isInitialized) {
        QVariantMap tmplConfig;
        QFile tmplConfigFile(tmplBasePath + QLatin1String("/config.json"));
        if (tmplConfigFile.exists()) {
            qCDebug(SK_CORE, "Found template configuration file.");
            if (tmplConfigFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
                QJsonParseError jpe;
                QJsonDocument tmplJsonConfig(QJsonDocument::fromJson(tmplConfigFile.readAll(), &jpe));
                if (jpe.error != QJsonParseError::NoError) {
                    qCCritical(SK_CORE, "Failed to parse template configuration file: %s", qUtf8Printable(jpe.errorString()));
                    return false;
                }

                tmplConfig = tmplJsonConfig.object().toVariantMap();
            } else {
                qCCritical(SK_CORE, "Failed to open template configuration file %s.", qUtf8Printable(tmplConfigFile.fileName()));
                return false;
            }
        }

        qCDebug(SK_CORE) << "Initializing configuration.";
        SkaffariConfig::load(engine()->config(QStringLiteral("Accounts")),
                             engine()->config(QStringLiteral("Admins")),
                             engine()->config(QStringLiteral("IMAP")),
                             tmplConfig);

        if (SkaffariConfig::imapUser().isEmpty()) {
            qCCritical(SK_CORE) << "No valid IMAP user defined.";
            return false;
        }

        if (SkaffariConfig::imapPassword().isEmpty()) {
            qCCritical(SK_CORE) << "No valid IMAP password defined.";
            return false;
        }

        // initialize DB one time to prevent https://bugreports.qt.io/browse/QTBUG-54872
        if (!initDb()) {
            return false;
        }

        SkaffariConfig::loadSettingsFromDB();

        isInitialized = true;
    }

    QString sitePath = tmplBasePath + QLatin1String("/site");

    auto view = new GrantleeView(this);
    view->setTemplateExtension(QStringLiteral(".html"));
    view->setWrapper(QStringLiteral("wrapper.html"));
	view->setCache(false);
    view->setIncludePaths({sitePath});
    view->engine()->addDefaultLibrary(QStringLiteral("grantlee_i18ntags"));
    view->engine()->addDefaultLibrary(QStringLiteral("grantlee_skaffari"));

    /* Start loading translations */
    const QString tmplTransFileName = QLatin1String("tmpl_") + tmplName;
    const QString tmplTransFilePath = tmplBasePath + QLatin1String("/l10n");

    for (const QString &lang : SKAFFARI_SUPPORTED_LANGS) {
        if (Q_LIKELY(lang != QLatin1String("en"))) {
            qCDebug(SK_CORE, "Loading translations for language %s.", qUtf8Printable(lang));
            const QLocale locale(lang);
            if (Q_LIKELY(locale.language() != QLocale::C)) {
                auto coreTrans = new QTranslator(this);
                if (Q_LIKELY(coreTrans->load(locale, QStringLiteral("skaffari"), QStringLiteral("_"), QStringLiteral(SKAFFARI_L10NDIR)))) {
                    addTranslator(locale, coreTrans);
                } else {
                    qCWarning(SK_CORE, "Failed to load core translation file for language %s from %s.", qUtf8Printable(locale.bcp47Name()), SKAFFARI_L10NDIR);
                }

                auto tmplTrans = new QTranslator(this);
                if (Q_LIKELY(tmplTrans->load(locale, tmplTransFileName, QStringLiteral("_"), tmplTransFilePath))) {
                    view->addTranslator(locale, tmplTrans);
                } else {
                    qCWarning(SK_CORE, "Failed to load template translation file for language %s from %s.", qUtf8Printable(locale.bcp47Name()), qUtf8Printable(tmplTransFilePath));
                }
            } else {
                qCWarning(SK_CORE, "Invalid language code: %s", qUtf8Printable(lang));
            }
        }
    }
    /* End loading translations */

	new Root(this);
	new Login(this);
	new Logout(this);
	new DomainEditor(this);
	new AccountEditor(this);
    new AdminEditor(this);
    new MyAccount(this);
    new SettingsEditor(this);

    auto staticSimple = new StaticSimple(this);
    QString staticPath = tmplBasePath + QLatin1String("/static");
    staticSimple->setIncludePaths({staticPath});

	new Session(this);

    new StatusMessage(this);

    auto auth = new Authentication(this);
    auto credential = new CredentialPassword(auth);
    credential->setPasswordType(CredentialPassword::Hashed);
    auto store = new AuthStoreSql(this);
    auto realm = new AuthenticationRealm(store, credential, auth);
    store->setParent(realm);
    auth->addRealm(store, credential);

    defaultHeaders().setHeader(QStringLiteral("X-Frame-Options"), QStringLiteral("DENY"));
    defaultHeaders().setHeader(QStringLiteral("X-Content-Type-Options"), QStringLiteral("nosniff"));
    defaultHeaders().setHeader(QStringLiteral("X-XSS-Protection"), QStringLiteral("1; mode=block"));
    defaultHeaders().setHeader(QStringLiteral("Content-Security-Policy"), QStringLiteral("default-src 'none'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; connect-src 'self';"));
    defaultHeaders().setHeader(QStringLiteral("X-Robots-Tag"), QStringLiteral("none"));

    return true;
}

bool Skaffari::postFork()
{

    initDb();

    return true;
}

bool Skaffari::initDb() const
{
    const QVariantMap dbconfig = engine()->config(QStringLiteral("Database"));
    const QString dbtype = dbconfig.value(QStringLiteral("type")).toString();
    const QString dbname = dbconfig.value(QStringLiteral("name")).toString();
    const QString dbuser = dbconfig.value(QStringLiteral("user")).toString();
    const QString dbpass = dbconfig.value(QStringLiteral("password")).toString();
    const QString dbhost = dbconfig.value(QStringLiteral("host"), QStringLiteral("localhost")).toString();
    const int dbport = dbconfig.value(QStringLiteral("port"), QStringLiteral("3306")).toInt();

    qCDebug(SK_CORE) << "Establishing database connection";
    QSqlDatabase db;
    const QString dbConName = Sql::databaseNameThread();
    if (dbtype == QLatin1String("QMYSQL")) {
        if (dbname.isEmpty()) {
            qCCritical(SK_CORE) << "No database name set!";
            return false;
        }
        if (dbuser.isEmpty()) {
            qCCritical(SK_CORE) << "No database user set!";
            return false;
        }
        if (dbpass.isEmpty()) {
            qCCritical(SK_CORE) << "No database password set!";
            return false;
        }

        db = QSqlDatabase::addDatabase(dbtype, dbConName);
        if (Q_LIKELY(db.isValid())) {
            db.setDatabaseName(dbname);
            db.setUserName(dbuser);
            db.setPassword(dbpass);

            if (dbhost[0] == QLatin1Char('/')) {
                db.setConnectOptions(QStringLiteral("UNIX_SOCKET=%1;MYSQL_OPT_RECONNECT=1;CLIENT_INTERACTIVE=1").arg(dbhost));
            } else {
                db.setConnectOptions(QStringLiteral("MYSQL_OPT_RECONNECT=1;CLIENT_INTERACTIVE=1"));
                db.setHostName(dbhost);
                db.setPort(dbport);
            }
        } else {
            qCCritical(SK_CORE) << "Failed to obtain database object.";
            return false;
        }
    } else {
        qCCritical(SK_CORE) << dbtype << "is not a supported database type.";
        return false;
    }

    if (Q_UNLIKELY(!db.open())) {
        qCCritical(SK_CORE) << "Failed to establish database connection:" << db.lastError().text();
        return false;
    }

    return true;
}

#include "moc_skaffari.cpp"
<|endoftext|>


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

#include "analogSensor.h"

#include <QtCore/QDebug>

#include <trikKernel/configurer.h>
#include <QsLog.h>

#include "i2cCommunicator.h"
#include "configurerHelper.h"

using namespace trikControl;

AnalogSensor::AnalogSensor(const QString &port, const trikKernel::Configurer &configurer, I2cCommunicator &communicator)
	: mCommunicator(communicator)
{
	mI2cCommandNumber = ConfigurerHelper::configureInt(configurer, mState, port, "i2cCommandNumber");
	mIRType = configurer.attributeByPort(port, "type") == "sharpGP2" ? Type::sharpGP2 : Type::analog;
	// We use linear subjection to normalize common analog sensor values:
	// normalizedValue = k * rawValue + b
	// To calculate k and b we need two raw values and two corresponding them normalized values.

	// We use hyperbolical subjection to normalize SharpGP2 sensor values:
	// normalizedValue = s / (rawValue + l) + n
	// To calculate s, l and n we need sensor readings at three distances.

	if (mIRType == Type::sharpGP2){
		CalculateLNS(port, configurer);
	} else {
		CalculateKB(port, configurer);
	}
	mState.ready();
}

AnalogSensor::Status AnalogSensor::status() const
{
	return DeviceInterface::combine(mCommunicator, mState.status());
}

int AnalogSensor::read()
{
	auto raw = readRawData();
	if (mIRType == Type::sharpGP2){
		return mS/(raw + mL) + mN;
	}
	return mK * raw + mB;
}

int AnalogSensor::readRawData()
{
	if (!mState.isReady() || mCommunicator.status() != DeviceInterface::Status::ready) {
		return 0;
	}

	QByteArray command(1, '\0');
	command[0] = static_cast<char>(mI2cCommandNumber & 0xFF);

	return mCommunicator.read(command);
}

void AnalogSensor::CalculateLNS(const QString &port, const trikKernel::Configurer &configurer)
{
	QStringList result;
	for (const QString &str : configurer.attributeByPort(port, "values").split(")")){
		result += str.mid(1).split(";");
	}
	const int x1 = result[0].toInt();
	const int y1 = result[1].toInt();
	const int x2 = result[2].toInt();
	const int y2 = result[3].toInt();
	const int x3 = result[4].toInt();
	const int y3 = result[5].toInt();

	// Counted from equations x1 = mS/(y1 + mL) + mN, x2 = mS/(y2 + mL) + mN, x3 = mS/(y3 + mL) + mN
	mL = (-x1 * y1 * y3 - x3 * y2 * y3 + x3 * y1 * y3 + x1 * y1 * y2 + x2 * y2 * y3 - x2 * y1 * y2) /
			(x1 * y3 - x2 * y3 + x2 * y1 - x1 * y2 + x3 * y2 - x3 * y1);
	mS = (x1 - x2) * (y1 + mL) * (y2 + mL) / (y2 - y1);
	mN = x1 - mS / (y1 + mL);
}

void AnalogSensor::CalculateKB(const QString &port, const trikKernel::Configurer &configurer)
{
	const int rawValue1 = ConfigurerHelper::configureInt(configurer, mState, port, "rawValue1");
	const int rawValue2 = ConfigurerHelper::configureInt(configurer, mState, port, "rawValue2");
	const int normalizedValue1 = ConfigurerHelper::configureInt(configurer, mState, port, "normalizedValue1");
	const int normalizedValue2 = ConfigurerHelper::configureInt(configurer, mState, port, "normalizedValue2");
	if (rawValue1 == rawValue2) {
		QLOG_ERROR() <<  "Sensor calibration error: rawValue1 = rawValue2!";
		mState.fail();
		mK = 0;
		mB = 0;
	} else {
		mK = static_cast<qreal>(normalizedValue2 - normalizedValue1) / (rawValue2 - rawValue1);
		mB = normalizedValue1 - mK * rawValue1;
	}
}
<commit_msg>Corrected the name of sensor type<commit_after>/* Copyright 2013 - 2015 Nikita Batov, Kseniya Gonta and CyberTech Labs Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "analogSensor.h"

#include <QtCore/QDebug>

#include <trikKernel/configurer.h>
#include <QsLog.h>

#include "i2cCommunicator.h"
#include "configurerHelper.h"

using namespace trikControl;

AnalogSensor::AnalogSensor(const QString &port, const trikKernel::Configurer &configurer, I2cCommunicator &communicator)
	: mCommunicator(communicator)
{
	mI2cCommandNumber = ConfigurerHelper::configureInt(configurer, mState, port, "i2cCommandNumber");
	mIRType = configurer.attributeByPort(port, "type") == "SharpGP2" ? Type::sharpGP2 : Type::analog;
	// We use linear subjection to normalize common analog sensor values:
	// normalizedValue = k * rawValue + b
	// To calculate k and b we need two raw values and two corresponding them normalized values.

	// We use hyperbolical subjection to normalize SharpGP2 sensor values:
	// normalizedValue = s / (rawValue + l) + n
	// To calculate s, l and n we need sensor readings at three distances.

	if (mIRType == Type::sharpGP2){
		CalculateLNS(port, configurer);
	} else {
		CalculateKB(port, configurer);
	}
	mState.ready();
}

AnalogSensor::Status AnalogSensor::status() const
{
	return DeviceInterface::combine(mCommunicator, mState.status());
}

int AnalogSensor::read()
{
	auto raw = readRawData();
	if (mIRType == Type::sharpGP2){
		return mS/(raw + mL) + mN;
	}
	return mK * raw + mB;
}

int AnalogSensor::readRawData()
{
	if (!mState.isReady() || mCommunicator.status() != DeviceInterface::Status::ready) {
		return 0;
	}

	QByteArray command(1, '\0');
	command[0] = static_cast<char>(mI2cCommandNumber & 0xFF);

	return mCommunicator.read(command);
}

void AnalogSensor::CalculateLNS(const QString &port, const trikKernel::Configurer &configurer)
{
	QStringList result;
	for (const QString &str : configurer.attributeByPort(port, "values").split(")")){
		result += str.mid(1).split(";");
	}
	const int x1 = result[0].toInt();
	const int y1 = result[1].toInt();
	const int x2 = result[2].toInt();
	const int y2 = result[3].toInt();
	const int x3 = result[4].toInt();
	const int y3 = result[5].toInt();

	// Counted from equations x1 = mS/(y1 + mL) + mN, x2 = mS/(y2 + mL) + mN, x3 = mS/(y3 + mL) + mN
	mL = (-x1 * y1 * y3 - x3 * y2 * y3 + x3 * y1 * y3 + x1 * y1 * y2 + x2 * y2 * y3 - x2 * y1 * y2) /
			(x1 * y3 - x2 * y3 + x2 * y1 - x1 * y2 + x3 * y2 - x3 * y1);
	mS = (x1 - x2) * (y1 + mL) * (y2 + mL) / (y2 - y1);
	mN = x1 - mS / (y1 + mL);
}

void AnalogSensor::CalculateKB(const QString &port, const trikKernel::Configurer &configurer)
{
	const int rawValue1 = ConfigurerHelper::configureInt(configurer, mState, port, "rawValue1");
	const int rawValue2 = ConfigurerHelper::configureInt(configurer, mState, port, "rawValue2");
	const int normalizedValue1 = ConfigurerHelper::configureInt(configurer, mState, port, "normalizedValue1");
	const int normalizedValue2 = ConfigurerHelper::configureInt(configurer, mState, port, "normalizedValue2");
	if (rawValue1 == rawValue2) {
		QLOG_ERROR() <<  "Sensor calibration error: rawValue1 = rawValue2!";
		mState.fail();
		mK = 0;
		mB = 0;
	} else {
		mK = static_cast<qreal>(normalizedValue2 - normalizedValue1) / (rawValue2 - rawValue1);
		mB = normalizedValue1 - mK * rawValue1;
	}
}
<|endoftext|>


<commit_before>///
/// anax
/// An open source C++ entity system.
///
/// Copyright (C) 2013-2014 Miguel Martin (miguel@miguel-martin.com)
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
///

#include <anax/World.hpp>

#include <anax/Config.hpp>

#include <anax/util/ContainerUtils.hpp>

#include <anax/detail/AnaxAssert.hpp>

namespace anax
{
    void World::SystemDeleter::operator() (detail::BaseSystem* system) const
    {
        system->m_world = nullptr;
        system->m_entities.clear();
    }

    World::World() :
        World(DEFAULT_ENTITY_POOL_SIZE)
    {
    }

    World::World(std::size_t entityPoolSize) :
        m_entityIdPool(entityPoolSize),
        m_entityAttributes(entityPoolSize)
    {
    }

    void World::removeAllSystems()
    {
        m_systems.clear();
    }

    Entity World::createEntity()
    {
        checkForResize(1);

        m_entityCache.alive.emplace_back(*this, m_entityIdPool.create());
        return m_entityCache.alive.back();
    }

    std::vector<Entity> World::createEntities(std::size_t amount)
    {
        std::vector<Entity> temp;
        temp.reserve(amount);

        checkForResize(amount);

        for(decltype(amount) i = 0; i < amount; ++i)
        {
            Entity e{*this, m_entityIdPool.create()};
            m_entityCache.alive.push_back(e);
            temp.push_back(e);
        }

        return temp;
    }

    void World::killEntity(Entity& entity)
    {
        // deactivate the entity
        deactivateEntity(entity);

        // now kill the entity (add it to the killed cache)
        m_entityCache.killed.push_back(entity);
    }

    void World::killEntities(std::vector<Entity>& entities)
    {
        for(auto& i : entities)
        {
            killEntity(i);
        }
    }

    void World::activateEntity(Entity& entity)
    {
        ANAX_ASSERT(isValid(entity), "invalid entity tried to be activated");

        m_entityCache.activated.push_back(entity);
    }

    void World::deactivateEntity(Entity& entity)
    {
        ANAX_ASSERT(isValid(entity), "invalid entity tried to be deactivated");

        m_entityCache.deactivated.push_back(entity);
    }

    bool World::isActivated(const Entity& entity) const
    {
        ANAX_ASSERT(isValid(entity), "invalid entity passed to isActivated");

        return m_entityAttributes.attributes[entity.getId().index].activated;
    }

    bool World::isValid(const anax::Entity &entity) const
    {
        return m_entityIdPool.isValid(entity.getId());
    }

    void World::refresh()
    {
        // go through all the activated entities from last call to refresh
        for(auto& entity : m_entityCache.activated)
        {
            auto& attribute = m_entityAttributes.attributes[entity.getId().index];
            attribute.activated = true;

            // loop through all the systems within the world
            for(auto& i : m_systems)
            {
                auto systemIndex = i.first;

                // if the entity passes the filter the system has and is not already part of the system
                if(i.second->getFilter().doesPassFilter(m_entityAttributes.componentStorage.getComponentTypeList(entity)))
                {
                    if(attribute.systems.size() <= systemIndex || !attribute.systems[systemIndex])
                    {
                        i.second->add(entity); // add it to the system

                        detail::EnsureCapacity(attribute.systems, systemIndex);
                        attribute.systems[systemIndex] = true;
                    }
                }
                // otherwise if the entity is within the system
                // and is not relevant to the system anymore...
                // note: the entity has already failed the filter
                else if(attribute.systems.size() > systemIndex && attribute.systems[systemIndex])
                {
                    // duplicate code (1)
                    i.second->remove(entity);
                    attribute.systems[systemIndex] = false;
                }
            }
        }

        // go through all the deactivated entities from last call to refresh
        for(auto& entity : m_entityCache.deactivated)
        {
            auto& attribute = m_entityAttributes.attributes[entity.getId().index];
            attribute.activated = false;

            // loop through all the systems within the world
            for(auto& i : m_systems)
            {
                auto systemIndex = i.first;
                if(attribute.systems.size() <= systemIndex) continue;

                if(attribute.systems[systemIndex])
                {
                    // duplicate code ...(1)
                    i.second->remove(entity);
                    attribute.systems[systemIndex] = false;
                }
            }
        }

        // go through all the killed entities from last call to refresh
        for(auto& entity : m_entityCache.killed)
        {
            // remove the entity from the alive array
            m_entityCache.alive.erase(std::remove(m_entityCache.alive.begin(), m_entityCache.alive.end(), entity), m_entityCache.alive.end());

            // destroy all the components it has
            m_entityAttributes.componentStorage.removeAllComponents(entity);

            // remove it from the id pool
            m_entityIdPool.remove(entity.getId());
        }

        // clear the temp cache
        m_entityCache.clearTemp();
    }

    void World::clear()
    {
        removeAllSystems(); // remove the systems

        // clear the attributes for all the entities
        m_entityAttributes.clear();

        // clear the entity cache
        m_entityCache.clear();

        // clear the id pool
        m_entityIdPool.clear();
    }

    std::size_t World::getEntityCount() const
    {
        return m_entityCache.alive.size();
    }

    const World::EntityArray& World::getEntities() const
    {
        return m_entityCache.alive;
    }

    void World::checkForResize(std::size_t amountOfEntitiesToBeAllocated)
    {
        auto newSize = getEntityCount() + amountOfEntitiesToBeAllocated;
        if(newSize > m_entityIdPool.getSize())
        {
            resize(newSize);
        }
    }

    void World::resize(std::size_t amount)
    {
        m_entityIdPool.resize(amount);
        m_entityAttributes.resize(amount);
    }

    void World::addSystem(detail::BaseSystem& system, detail::TypeId systemTypeId)
    {
        ANAX_ASSERT(!system.m_world, "System is already contained within a World");

        m_systems[systemTypeId].reset(&system);

        system.m_world = this;
        system.initialize();
    }

    void World::removeSystem(detail::TypeId systemTypeId)
    {
        ANAX_ASSERT(doesSystemExist(systemTypeId), "System does not exist in world");
        m_systems.erase(systemTypeId);
    }

    bool World::doesSystemExist(detail::TypeId systemTypeId) const
    {
        return m_systems.find(systemTypeId) != m_systems.end();
    }

    Entity World::getEntity(std::size_t index)
    {
        return Entity{*this, m_entityIdPool.get(index)};
    }
}
<commit_msg>include algorithm for std::remove<commit_after>///
/// anax
/// An open source C++ entity system.
///
/// Copyright (C) 2013-2014 Miguel Martin (miguel@miguel-martin.com)
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
///

#include <anax/World.hpp>

#include <algorithm>

#include <anax/Config.hpp>

#include <anax/detail/AnaxAssert.hpp>
#include <anax/util/ContainerUtils.hpp>

namespace anax
{
    void World::SystemDeleter::operator() (detail::BaseSystem* system) const
    {
        system->m_world = nullptr;
        system->m_entities.clear();
    }

    World::World() :
        World(DEFAULT_ENTITY_POOL_SIZE)
    {
    }

    World::World(std::size_t entityPoolSize) :
        m_entityIdPool(entityPoolSize),
        m_entityAttributes(entityPoolSize)
    {
    }

    void World::removeAllSystems()
    {
        m_systems.clear();
    }

    Entity World::createEntity()
    {
        checkForResize(1);

        m_entityCache.alive.emplace_back(*this, m_entityIdPool.create());
        return m_entityCache.alive.back();
    }

    std::vector<Entity> World::createEntities(std::size_t amount)
    {
        std::vector<Entity> temp;
        temp.reserve(amount);

        checkForResize(amount);

        for(decltype(amount) i = 0; i < amount; ++i)
        {
            Entity e{*this, m_entityIdPool.create()};
            m_entityCache.alive.push_back(e);
            temp.push_back(e);
        }

        return temp;
    }

    void World::killEntity(Entity& entity)
    {
        // deactivate the entity
        deactivateEntity(entity);

        // now kill the entity (add it to the killed cache)
        m_entityCache.killed.push_back(entity);
    }

    void World::killEntities(std::vector<Entity>& entities)
    {
        for(auto& i : entities)
        {
            killEntity(i);
        }
    }

    void World::activateEntity(Entity& entity)
    {
        ANAX_ASSERT(isValid(entity), "invalid entity tried to be activated");

        m_entityCache.activated.push_back(entity);
    }

    void World::deactivateEntity(Entity& entity)
    {
        ANAX_ASSERT(isValid(entity), "invalid entity tried to be deactivated");

        m_entityCache.deactivated.push_back(entity);
    }

    bool World::isActivated(const Entity& entity) const
    {
        ANAX_ASSERT(isValid(entity), "invalid entity passed to isActivated");

        return m_entityAttributes.attributes[entity.getId().index].activated;
    }

    bool World::isValid(const anax::Entity &entity) const
    {
        return m_entityIdPool.isValid(entity.getId());
    }

    void World::refresh()
    {
        // go through all the activated entities from last call to refresh
        for(auto& entity : m_entityCache.activated)
        {
            auto& attribute = m_entityAttributes.attributes[entity.getId().index];
            attribute.activated = true;

            // loop through all the systems within the world
            for(auto& i : m_systems)
            {
                auto systemIndex = i.first;

                // if the entity passes the filter the system has and is not already part of the system
                if(i.second->getFilter().doesPassFilter(m_entityAttributes.componentStorage.getComponentTypeList(entity)))
                {
                    if(attribute.systems.size() <= systemIndex || !attribute.systems[systemIndex])
                    {
                        i.second->add(entity); // add it to the system

                        detail::EnsureCapacity(attribute.systems, systemIndex);
                        attribute.systems[systemIndex] = true;
                    }
                }
                // otherwise if the entity is within the system
                // and is not relevant to the system anymore...
                // note: the entity has already failed the filter
                else if(attribute.systems.size() > systemIndex && attribute.systems[systemIndex])
                {
                    // duplicate code (1)
                    i.second->remove(entity);
                    attribute.systems[systemIndex] = false;
                }
            }
        }

        // go through all the deactivated entities from last call to refresh
        for(auto& entity : m_entityCache.deactivated)
        {
            auto& attribute = m_entityAttributes.attributes[entity.getId().index];
            attribute.activated = false;

            // loop through all the systems within the world
            for(auto& i : m_systems)
            {
                auto systemIndex = i.first;
                if(attribute.systems.size() <= systemIndex) continue;

                if(attribute.systems[systemIndex])
                {
                    // duplicate code ...(1)
                    i.second->remove(entity);
                    attribute.systems[systemIndex] = false;
                }
            }
        }

        // go through all the killed entities from last call to refresh
        for(auto& entity : m_entityCache.killed)
        {
            // remove the entity from the alive array
            m_entityCache.alive.erase(std::remove(m_entityCache.alive.begin(), m_entityCache.alive.end(), entity), m_entityCache.alive.end());

            // destroy all the components it has
            m_entityAttributes.componentStorage.removeAllComponents(entity);

            // remove it from the id pool
            m_entityIdPool.remove(entity.getId());
        }

        // clear the temp cache
        m_entityCache.clearTemp();
    }

    void World::clear()
    {
        removeAllSystems(); // remove the systems

        // clear the attributes for all the entities
        m_entityAttributes.clear();

        // clear the entity cache
        m_entityCache.clear();

        // clear the id pool
        m_entityIdPool.clear();
    }

    std::size_t World::getEntityCount() const
    {
        return m_entityCache.alive.size();
    }

    const World::EntityArray& World::getEntities() const
    {
        return m_entityCache.alive;
    }

    void World::checkForResize(std::size_t amountOfEntitiesToBeAllocated)
    {
        auto newSize = getEntityCount() + amountOfEntitiesToBeAllocated;
        if(newSize > m_entityIdPool.getSize())
        {
            resize(newSize);
        }
    }

    void World::resize(std::size_t amount)
    {
        m_entityIdPool.resize(amount);
        m_entityAttributes.resize(amount);
    }

    void World::addSystem(detail::BaseSystem& system, detail::TypeId systemTypeId)
    {
        ANAX_ASSERT(!system.m_world, "System is already contained within a World");

        m_systems[systemTypeId].reset(&system);

        system.m_world = this;
        system.initialize();
    }

    void World::removeSystem(detail::TypeId systemTypeId)
    {
        ANAX_ASSERT(doesSystemExist(systemTypeId), "System does not exist in world");
        m_systems.erase(systemTypeId);
    }

    bool World::doesSystemExist(detail::TypeId systemTypeId) const
    {
        return m_systems.find(systemTypeId) != m_systems.end();
    }

    Entity World::getEntity(std::size_t index)
    {
        return Entity{*this, m_entityIdPool.get(index)};
    }
}
<|endoftext|>


<commit_before>#include "archive.hh"
#include "pool.hh"
#include "remote-store.hh"
#include "serve-protocol.hh"
#include "store-api.hh"
#include "worker-protocol.hh"
#include "ssh.hh"

namespace nix {

static std::string uriScheme = "legacy-ssh://";

struct LegacySSHStore : public Store
{
    struct Connection
    {
        std::unique_ptr<SSHMaster::Connection> sshConn;
        FdSink to;
        FdSource from;
    };

    std::string host;

    ref<Pool<Connection>> connections;

    SSHMaster master;

    LegacySSHStore(const string & host, const Params & params)
        : Store(params)
        , host(host)
        , connections(make_ref<Pool<Connection>>(
            std::max(1, std::stoi(get(params, "max-connections", "1"))),
            [this]() { return openConnection(); },
            [](const ref<Connection> & r) { return true; }
            ))
        , master(
            host,
            get(params, "ssh-key", ""),
            // Use SSH master only if using more than 1 connection.
            connections->capacity() > 1,
            get(params, "compress", "") == "true")
    {
    }

    ref<Connection> openConnection()
    {
        auto conn = make_ref<Connection>();
        conn->sshConn = master.startCommand("nix-store --serve");
        conn->to = FdSink(conn->sshConn->in.get());
        conn->from = FdSource(conn->sshConn->out.get());

        int remoteVersion;

        try {
            conn->to << SERVE_MAGIC_1 << SERVE_PROTOCOL_VERSION;
            conn->to.flush();

            unsigned int magic = readInt(conn->from);
            if (magic != SERVE_MAGIC_2)
                throw Error("protocol mismatch with ‘nix-store --serve’ on ‘%s’", host);
            remoteVersion = readInt(conn->from);
            if (GET_PROTOCOL_MAJOR(remoteVersion) != 0x200)
                throw Error("unsupported ‘nix-store --serve’ protocol version on ‘%s’", host);

        } catch (EndOfFile & e) {
            throw Error("cannot connect to ‘%1%’", host);
        }

        return conn;
    };

    string getUri() override
    {
        return uriScheme + host;
    }

    void queryPathInfoUncached(const Path & path,
        std::function<void(std::shared_ptr<ValidPathInfo>)> success,
        std::function<void(std::exception_ptr exc)> failure) override
    {
        sync2async<std::shared_ptr<ValidPathInfo>>(success, failure, [&]() -> std::shared_ptr<ValidPathInfo> {
            auto conn(connections->get());

            debug("querying remote host ‘%s’ for info on ‘%s’", host, path);

            conn->to << cmdQueryPathInfos << PathSet{path};
            conn->to.flush();

            auto info = std::make_shared<ValidPathInfo>();
            conn->from >> info->path;
            if (info->path.empty()) return nullptr;
            assert(path == info->path);

            PathSet references;
            conn->from >> info->deriver;
            info->references = readStorePaths<PathSet>(*this, conn->from);
            readLongLong(conn->from); // download size
            info->narSize = readLongLong(conn->from);

            auto s = readString(conn->from);
            assert(s == "");

            return info;
        });
    }

    void addToStore(const ValidPathInfo & info, const ref<std::string> & nar,
        bool repair, bool dontCheckSigs,
        std::shared_ptr<FSAccessor> accessor) override
    {
        debug("adding path ‘%s’ to remote host ‘%s’", info.path, host);

        auto conn(connections->get());

        conn->to
            << cmdImportPaths
            << 1;
        conn->to(*nar);
        conn->to
            << exportMagic
            << info.path
            << info.references
            << info.deriver
            << 0
            << 0;
        conn->to.flush();

        if (readInt(conn->from) != 1)
            throw Error("failed to add path ‘%s’ to remote host ‘%s’, info.path, host");

    }

    void narFromPath(const Path & path, Sink & sink) override
    {
        auto conn(connections->get());

        conn->to << cmdDumpStorePath << path;
        conn->to.flush();

        /* FIXME: inefficient. */
        ParseSink parseSink; /* null sink; just parse the NAR */
        TeeSource savedNAR(conn->from);
        parseDump(parseSink, savedNAR);
        sink(*savedNAR.data);
    }

    /* Unsupported methods. */
    [[noreturn]] void unsupported()
    {
        throw Error("operation not supported on SSH stores");
    }

    PathSet queryAllValidPaths() override { unsupported(); }

    void queryReferrers(const Path & path, PathSet & referrers) override
    { unsupported(); }

    PathSet queryDerivationOutputs(const Path & path) override
    { unsupported(); }

    StringSet queryDerivationOutputNames(const Path & path) override
    { unsupported(); }

    Path queryPathFromHashPart(const string & hashPart) override
    { unsupported(); }

    Path addToStore(const string & name, const Path & srcPath,
        bool recursive, HashType hashAlgo,
        PathFilter & filter, bool repair) override
    { unsupported(); }

    Path addTextToStore(const string & name, const string & s,
        const PathSet & references, bool repair) override
    { unsupported(); }

    void buildPaths(const PathSet & paths, BuildMode buildMode) override
    { unsupported(); }

    BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv,
        BuildMode buildMode) override
    { unsupported(); }

    void ensurePath(const Path & path) override
    { unsupported(); }

    void addTempRoot(const Path & path) override
    { unsupported(); }

    void addIndirectRoot(const Path & path) override
    { unsupported(); }

    Roots findRoots() override
    { unsupported(); }

    void collectGarbage(const GCOptions & options, GCResults & results) override
    { unsupported(); }

    ref<FSAccessor> getFSAccessor() override
    { unsupported(); }

    void addSignatures(const Path & storePath, const StringSet & sigs) override
    { unsupported(); }

    bool isTrusted() override
    { return true; }

};

static RegisterStoreImplementation regStore([](
    const std::string & uri, const Store::Params & params)
    -> std::shared_ptr<Store>
{
    if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0;
    return std::make_shared<LegacySSHStore>(std::string(uri, uriScheme.size()), params);
});

}
<commit_msg>Fix nix-copy-closure --to<commit_after>#include "archive.hh"
#include "pool.hh"
#include "remote-store.hh"
#include "serve-protocol.hh"
#include "store-api.hh"
#include "worker-protocol.hh"
#include "ssh.hh"

namespace nix {

static std::string uriScheme = "legacy-ssh://";

struct LegacySSHStore : public Store
{
    struct Connection
    {
        std::unique_ptr<SSHMaster::Connection> sshConn;
        FdSink to;
        FdSource from;
    };

    std::string host;

    ref<Pool<Connection>> connections;

    SSHMaster master;

    LegacySSHStore(const string & host, const Params & params)
        : Store(params)
        , host(host)
        , connections(make_ref<Pool<Connection>>(
            std::max(1, std::stoi(get(params, "max-connections", "1"))),
            [this]() { return openConnection(); },
            [](const ref<Connection> & r) { return true; }
            ))
        , master(
            host,
            get(params, "ssh-key", ""),
            // Use SSH master only if using more than 1 connection.
            connections->capacity() > 1,
            get(params, "compress", "") == "true")
    {
    }

    ref<Connection> openConnection()
    {
        auto conn = make_ref<Connection>();
        conn->sshConn = master.startCommand("nix-store --serve --write");
        conn->to = FdSink(conn->sshConn->in.get());
        conn->from = FdSource(conn->sshConn->out.get());

        int remoteVersion;

        try {
            conn->to << SERVE_MAGIC_1 << SERVE_PROTOCOL_VERSION;
            conn->to.flush();

            unsigned int magic = readInt(conn->from);
            if (magic != SERVE_MAGIC_2)
                throw Error("protocol mismatch with ‘nix-store --serve’ on ‘%s’", host);
            remoteVersion = readInt(conn->from);
            if (GET_PROTOCOL_MAJOR(remoteVersion) != 0x200)
                throw Error("unsupported ‘nix-store --serve’ protocol version on ‘%s’", host);

        } catch (EndOfFile & e) {
            throw Error("cannot connect to ‘%1%’", host);
        }

        return conn;
    };

    string getUri() override
    {
        return uriScheme + host;
    }

    void queryPathInfoUncached(const Path & path,
        std::function<void(std::shared_ptr<ValidPathInfo>)> success,
        std::function<void(std::exception_ptr exc)> failure) override
    {
        sync2async<std::shared_ptr<ValidPathInfo>>(success, failure, [&]() -> std::shared_ptr<ValidPathInfo> {
            auto conn(connections->get());

            debug("querying remote host ‘%s’ for info on ‘%s’", host, path);

            conn->to << cmdQueryPathInfos << PathSet{path};
            conn->to.flush();

            auto info = std::make_shared<ValidPathInfo>();
            conn->from >> info->path;
            if (info->path.empty()) return nullptr;
            assert(path == info->path);

            PathSet references;
            conn->from >> info->deriver;
            info->references = readStorePaths<PathSet>(*this, conn->from);
            readLongLong(conn->from); // download size
            info->narSize = readLongLong(conn->from);

            auto s = readString(conn->from);
            assert(s == "");

            return info;
        });
    }

    void addToStore(const ValidPathInfo & info, const ref<std::string> & nar,
        bool repair, bool dontCheckSigs,
        std::shared_ptr<FSAccessor> accessor) override
    {
        debug("adding path ‘%s’ to remote host ‘%s’", info.path, host);

        auto conn(connections->get());

        conn->to
            << cmdImportPaths
            << 1;
        conn->to(*nar);
        conn->to
            << exportMagic
            << info.path
            << info.references
            << info.deriver
            << 0
            << 0;
        conn->to.flush();

        if (readInt(conn->from) != 1)
            throw Error("failed to add path ‘%s’ to remote host ‘%s’, info.path, host");

    }

    void narFromPath(const Path & path, Sink & sink) override
    {
        auto conn(connections->get());

        conn->to << cmdDumpStorePath << path;
        conn->to.flush();

        /* FIXME: inefficient. */
        ParseSink parseSink; /* null sink; just parse the NAR */
        TeeSource savedNAR(conn->from);
        parseDump(parseSink, savedNAR);
        sink(*savedNAR.data);
    }

    /* Unsupported methods. */
    [[noreturn]] void unsupported()
    {
        throw Error("operation not supported on SSH stores");
    }

    PathSet queryAllValidPaths() override { unsupported(); }

    void queryReferrers(const Path & path, PathSet & referrers) override
    { unsupported(); }

    PathSet queryDerivationOutputs(const Path & path) override
    { unsupported(); }

    StringSet queryDerivationOutputNames(const Path & path) override
    { unsupported(); }

    Path queryPathFromHashPart(const string & hashPart) override
    { unsupported(); }

    Path addToStore(const string & name, const Path & srcPath,
        bool recursive, HashType hashAlgo,
        PathFilter & filter, bool repair) override
    { unsupported(); }

    Path addTextToStore(const string & name, const string & s,
        const PathSet & references, bool repair) override
    { unsupported(); }

    void buildPaths(const PathSet & paths, BuildMode buildMode) override
    { unsupported(); }

    BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv,
        BuildMode buildMode) override
    { unsupported(); }

    void ensurePath(const Path & path) override
    { unsupported(); }

    void addTempRoot(const Path & path) override
    { unsupported(); }

    void addIndirectRoot(const Path & path) override
    { unsupported(); }

    Roots findRoots() override
    { unsupported(); }

    void collectGarbage(const GCOptions & options, GCResults & results) override
    { unsupported(); }

    ref<FSAccessor> getFSAccessor() override
    { unsupported(); }

    void addSignatures(const Path & storePath, const StringSet & sigs) override
    { unsupported(); }

    bool isTrusted() override
    { return true; }

};

static RegisterStoreImplementation regStore([](
    const std::string & uri, const Store::Params & params)
    -> std::shared_ptr<Store>
{
    if (std::string(uri, 0, uriScheme.size()) != uriScheme) return 0;
    return std::make_shared<LegacySSHStore>(std::string(uri, uriScheme.size()), params);
});

}
<|endoftext|>


<commit_before><commit_msg>desktop: avoid loading to-be-recovered documents when recovery is disabled<commit_after><|endoftext|>