<commit_before>#include <atma/xtm/bind.hpp>

#include <memory>
#include <functional>

namespace detail
{
	uint const fn_size = 32;
	uint const fn_bufsize = fn_size - sizeof(void*) - sizeof(void*);

	using functor_buf_t = char[fn_bufsize];

	template <typename T>
	struct is_inplace_allowed_t
	{
		static bool const value = sizeof(T) <= fn_bufsize;
	};

	template <typename FN>
	struct base_dispatch_t;

	template <typename R, typename... Params>
	struct base_dispatch_t<R(Params...)>
	{
		virtual auto operator ()(Params&&... args) -> R = 0;
	};

	template <typename FN>
	using base_dispatch_ptr = std::unique_ptr<base_dispatch_t<FN>>;

	template <typename FN>
	struct memfnptr_dispatch_t;

	template <typename R, typename C, typename... Params>
	struct memfnptr_dispatch_t<R (C::*)(Params...)>
		: base_dispatch_t<R(Params...)>
	{
		auto operator ()(C* c, Params&&... args) -> R override
		{
			return (c->*fn_)(std::forward<Params>(args)...);
		}

	private:
		R (C::*fn_)(Params...);
	};

	template <typename R, typename... Params>
	struct fnptr_dispatch_t
		: base_dispatch_t<R(Params...)>
	{
		fnptr_dispatch_t(R (*fn)(Params...))
			: fn_{fn}
		{}

		auto operator ()(Params&&... args) -> R override
		{
			return (*fn_)(std::forward<Params>(args)...);
		}

	private:
		R (*fn_)(Params...);
	};

	template <typename T>
	auto functorize(T&& t) -> T
	{
		return std::forward<T>(t);
	}

	template <typename R, typename C, typename... Params>
	auto functorize(R (C::*fn)(Params...)) -> decltype(std::mem_fn(fn))
	{
		return std::mem_fn(fn);
	}

	template <typename R, typename C, typename... Params>
	auto functorize(R(C::*fn)(Params...) const) -> decltype(std::mem_fn(fn))
	{
		return std::mem_fn(fn);
	}

	template <typename FN, bool = is_inplace_allowed_t<FN>::value>
	struct dispatch_central_t
	{
		static auto store(functor_buf_t& buf, FN const& fn) -> void
		{
			new (&buf) FN(fn);
		}

		static auto destruct(functor_buf_t& fn) -> void
		{
			reinterpret_cast<FN&>(fn).~FN();
		}

		template <typename R, typename... Args>
		static auto call(functor_buf_t& buf, Args... args) -> R
		{
			auto&& fn = reinterpret_cast<FN&>(buf);
			return fn(std::forward<Args>(args)...);
		}
	};

	template <typename FN>
	struct dispatch_central_t<FN, false>
	{
		static auto store(functor_buf_t& buf, FN const& fn) -> void
		{
			reinterpret_cast<FN*&>(buf) = new FN(fn);
		}

		static auto destruct(functor_buf_t& buf) -> void
		{
			delete reinterpret_cast<FN*&>(buf);
		}

		template <typename R, typename... Args>
		static auto call(functor_buf_t& buf, Args... args) -> R
		{
			return reinterpret_cast<FN*&>(buf)->operator ()(std::forward<Args>(args)...);
		}
	};

	struct functor_vtable_t
	{
		void (*const destruct)(detail::functor_buf_t&);
	};

	template <typename FN>
	auto destruct_functor(functor_buf_t& buf) -> void
	{
		dispatch_central_t<FN>::destruct(buf);
	}

	template <typename FN>
	auto generate_vtable() -> functor_vtable_t&
	{
		static functor_vtable_t _ = {&destruct_functor<FN>};
		return _;
	}
}

template <typename> struct fn_t;

template <typename R, typename... Params>
struct fn_t<R(Params...)>
{
	template <typename FN>
	fn_t(FN&& fn)
		: vtable_()
		, dispatch_()
	{
		functor_init(detail::functorize(std::forward<FN>(fn)));
	}

	~fn_t()
	{
		vtable_->destruct(buf_);
	}

	template <typename... Args>
	auto operator ()(Args&&... args) -> R
	{
		return dispatch_(buf_, std::forward<Args>(args)...);
	}

private:
	template <typename FN>
	auto functor_init(FN&& fn) -> void
	{
		vtable_ = &detail::generate_vtable<FN>();
		dispatch_ = &detail::dispatch_central_t<FN>::template call<R, Params...>;
		detail::dispatch_central_t<FN>::store(buf_, std::forward<FN>(fn));
	}

private:
	detail::functor_vtable_t* vtable_;
	R (*dispatch_)(detail::functor_buf_t&, Params...);
	detail::functor_buf_t buf_;
};

int plus(int a, int b) { return a + b; }

struct dragon_t
{
	int plus(int a, int b) { return a + b; }
};

int function_main()
{
	auto f = fn_t<int(int, int)>{&plus};
	auto r = f(3, 4);

	auto d = dragon_t();

	//auto x = atma::xtm::curry(&dragon_t::plus, &d);
	//auto x2 = new decltype(x)(x);
	//auto xr = (*x2)(3, 4);

	std::function<int(int, int)> sf = atma::xtm::curry(&dragon_t::plus, &d);
	//auto r2 = sf(4, 5);

	auto f2 = fn_t<int(int, int)>{atma::xtm::curry(&dragon_t::plus, &d)};
	auto r2 = f2(4, 5);

	auto f3 = fn_t<int(dragon_t&, int, int)>{std::mem_fn(&dragon_t::plus)};
	auto r3 = f3(d, 3, 3);

	return sizeof(atma::xtm::curry(&dragon_t::plus, &d));
}

<commit_msg>things<commit_after>#include <atma/xtm/bind.hpp>

#include <memory>
#include <functional>
#include <tuple>

namespace detail
{
	uint const fn_size = 32;
	uint const fn_bufsize = fn_size - sizeof(void*) - sizeof(void*);

	//using functor_buf_t = char[fn_bufsize];
	struct functor_buf_t
	{
		char pad[fn_bufsize];
	};

	template <typename, typename...>
	struct functor_vtable_t;

	template <typename T>
	struct is_inplace_allowed_t
	{
		static bool const value = sizeof(T) <= fn_bufsize;
	};

	template <typename T>
	auto functorize(T&& t) -> T
	{
		return t;
	}

	template <typename R, typename C, typename... Params>
	auto functorize(R (C::*fn)(Params...)) -> decltype(std::mem_fn(fn))
	{
		return std::mem_fn(fn);
	}

	template <typename R, typename C, typename... Params>
	auto functorize(R(C::*fn)(Params...) const) -> decltype(std::mem_fn(fn))
	{
		return std::mem_fn(fn);
	}

	template <typename FN, bool = is_inplace_allowed_t<FN>::value>
	struct dispatch_central_t;

	template <typename FN>
	struct dispatch_central_t<FN, true>
	{
		static auto store(functor_buf_t& buf, FN const& fn) -> void
		{
			new (&buf) FN(fn);
		}

		static auto move(functor_buf_t& dest, functor_buf_t&& src) -> void
		{
			auto&& rhs = reinterpret_cast<FN&&>(src);
			new (&dest) FN(std::move(rhs));
		}

		static auto destruct(functor_buf_t& fn) -> void
		{
			reinterpret_cast<FN&>(fn).~FN();
		}

		template <typename R, typename... Args>
		static auto call(functor_buf_t& buf, Args... args) -> R
		{
			auto& fn = reinterpret_cast<FN&>(buf);
			return fn(std::forward<Args>(args)...);
		}
	};

	template <typename FN>
	struct dispatch_central_t<FN, false>
	{
		static auto store(functor_buf_t& buf, FN const& fn) -> void
		{
			reinterpret_cast<FN*&>(buf) = new FN(fn);
		}

		static auto move(functor_buf_t& dest, functor_buf_t&& src) -> void
		{
			//auto&& lhs = reinterpret_cast<FN*&>(dest);
			//lhs = new FN(*reinterpret_cast<FN* const&>(src));
			//auto&& rhs = ;
			//lhs = rhs;
		}

		static auto destruct(functor_buf_t& buf) -> void
		{
			delete reinterpret_cast<FN*&>(buf);
		}

		template <typename R, typename... Args>
		static auto call(functor_buf_t& buf, Args... args) -> R
		{
			//return reinterpret_cast<FN*>(&buf)->operator ()(std::forward<Args>(args)...);
			return R();
		}
	};

	template <typename R, typename ParamsTuple>
	struct functor_vtable_call_partial_t;

	template <typename R, typename... Params>
	struct functor_vtable_call_partial_t<R, std::tuple<Params...>>
	{
		auto (*call)(Params...) -> std::function<R(Params...)>;
	};

	template <size_t S, typename R, typename ParamsTuple>
	struct functor_vtable_call_t;

	// proper call
	template <typename R, typename... Params>
	struct functor_vtable_call_t<sizeof...(Params), R, std::tuple<Params...>>
		: functor_vtable_call_t<(sizeof...(Params)) - 1, R, std::tuple<Params...>>
	{
		auto (*call)(Params...) -> R;
	};

	// partial call
	template <size_t S, typename R, typename... Params>
	struct functor_vtable_call_t<S, R, std::tuple<Params...>>
		: functor_vtable_call_t<S - 1, R, std::tuple<Params...>>
		, functor_vtable_call_partial_t<R, atma::xtm::tuple_select_t<atma::xtm::idxs_list_t<S - 1>, std::tuple<Params...>>>
	{
	};

	// terminate
	template <typename R, typename... Params>
	struct functor_vtable_call_t<0, R, std::tuple<Params...>>
	{
	};

	template <typename R, typename... Params>
	struct functor_vtable_t
		: functor_vtable_call_t<sizeof...(Params), R, std::tuple<Params...>>
	{
		using move_fntype = void(*)(detail::functor_buf_t&, detail::functor_buf_t&&);
		using destruct_fntype = void(*)(detail::functor_buf_t&);

		functor_vtable_t(move_fntype move, destruct_fntype destruct)
			: move(move)
			, destruct(destruct)
		{}

		//functor_vtable_t
		//R (*const call)(Params...);
		move_fntype move;
		destruct_fntype destruct;
		//void(*const move)(detail::functor_buf_t&, detail::functor_buf_t&&);
		//void(*const destruct)(detail::functor_buf_t&);
	};

	template <typename R, typename... Params>
	struct functor_wrapper_t
	{
		functor_wrapper_t()
			: vtable_()
		{}

		template <typename FN>
		functor_wrapper_t(FN&& fn)
			: vtable_(generate_vtable<FN, R, Params...>())
		{
			dispatch_central_t<FN>::store(buf_, std::forward<FN>(fn));
		}

		~functor_wrapper_t()
		{
			if (vtable_)
				vtable_->destruct(buf_);
		}

		auto move_into(functor_wrapper_t& rhs) -> void
		{
			vtable_->move(rhs.buf_, std::move(buf_));
			rhs.vtable_ = vtable_;

			vtable_->destruct(buf_);
		}

	public:
		functor_vtable_t<R, Params...>* vtable_;
		functor_buf_t buf_;
	};

	template <typename FN>
	auto destruct_functor(functor_buf_t& buf) -> void
	{
		dispatch_central_t<FN>::destruct(buf);
	}

	template <typename FN>
	auto move_functor(functor_buf_t& dest, functor_buf_t&& src) -> void
	{
		dispatch_central_t<FN>::move(dest, std::move(src));
	}

	template <typename FN, typename R, typename... Params>
	auto generate_vtable() -> functor_vtable_t<R, Params...>*
	{
		static auto _ = functor_vtable_t<R, Params...>{
			&dispatch_central_t<FN>::move,
			&destruct_functor<FN>
		};

		return &_;
	}
}

template <typename> struct fn_t;

template <typename R, typename... Params>
struct fn_t<R(Params...)>
{
	template <typename FN>
	fn_t(FN&& fn)
		: dispatch_()
	{
		functor_init(detail::functorize(std::forward<FN>(fn)));
	}

	template <typename... Args>
	auto operator ()(Args&&... args) -> R
	{
		return dispatch_(wrapper_.buf_, std::forward<Args>(args)...);
	}

	auto swap(fn_t& rhs) -> void
	{
		auto tmp = detail::functor_wrapper_t{};
		rhs.wrapper_.move_into(tmp);
		wrapper_.move_into(rhs.wrapper_);
		tmp.move_into(wrapper_);
	}

private:
	template <typename FN>
	auto functor_init(FN&& fn) -> void
	{
		dispatch_ = &detail::dispatch_central_t<FN>::template call<R, Params...>;
		wrapper_ = detail::functor_wrapper_t<R, Params...>{std::forward<FN>(fn)};
	}

private:
	R (*dispatch_)(detail::functor_buf_t&, Params...);
	//detail::functor_vtable_t* vtable_;
	//detail::functor_buf_t buf_;
	detail::functor_wrapper_t<R, Params...> wrapper_;
};

int plus(int a, int b) { return a + b; }

struct dragon_t
{
	int plus(int a, int b) { return a + b; }
	int plus3(int a) { return a + 3; }
};

int function_main()
{
	auto f = fn_t<int(int, int)>{&plus};
	auto r = f(3, 4);

	auto d = dragon_t();

	//auto x = atma::xtm::curry(&dragon_t::plus, &d);
	//auto x2 = new decltype(x)(x);
	//auto xr = (*x2)(3, 4);

	std::function<int(int, int)> sf = atma::xtm::curry(&dragon_t::plus, &d);
	//auto r2 = sf(4, 5);

	auto f2 = fn_t<int(int, int)>{atma::xtm::curry(&dragon_t::plus, &d)};
	auto r2 = f2(4, 5);

	auto f3 = fn_t<int(dragon_t&, int, int)>{std::mem_fn(&dragon_t::plus)};
	auto r3 = f3(d, 3, 3);

	auto f4 = fn_t<int(int)>{atma::xtm::curry(&dragon_t::plus3, &d)};
	auto r4 = f4(4);

	return sizeof(atma::xtm::curry(&dragon_t::plus3, &d));
}

<|endoftext|>


<commit_before>#include "fenceview.h"
// OSG
#include <osg/ShapeDrawable>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Vec4>
#include <osg/PositionAttitudeTransform>
#include <osg/ref_ptr>

// troen
#include "../constants.h"
#include "shaders.h"
#include "../model/fencemodel.h"
#include "../controller/fencecontroller.h"

using namespace troen;

FenceView::FenceView(FenceController* fenceController, osg::Vec3 color, std::shared_ptr<AbstractModel>& model)
{
	AbstractView();
	m_playerColor = color;
	m_model = std::static_pointer_cast<FenceModel>(model);
	m_node = new osg::Group();

	m_fenceController = fenceController;

	initializeFence();
	initializeShader();
}

void FenceView::initializeFence()
{
	m_fenceHeight = FENCE_HEIGHT_VIEW;

	m_coordinates = new osg::Vec3Array;
	m_coordinates->setDataVariance(osg::Object::DYNAMIC);

	m_relativeHeights = new osg::FloatArray;
	m_relativeHeights->setDataVariance(osg::Object::DYNAMIC);

	m_geometry = new osg::Geometry();
	m_geometry->setVertexArray(m_coordinates);

	// set the relative height between 0 and 1 as an additional vertex attribute
	m_geometry->setVertexAttribArray(5, m_relativeHeights);
	m_geometry->setVertexAttribBinding(5, osg::Geometry::BIND_PER_VERTEX);

	// seems to be important so that we won't crash after 683 fence parts
	m_geometry->setUseDisplayList(false);

	// use the shared normal array.
	// polyGeom->setNormalArray(shared_normals.get(), osg::Array::BIND_OVERALL);

	m_drawArrays = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP, 0, 0);
	m_geometry->addPrimitiveSet(m_drawArrays);

	m_geode = new osg::Geode();
	m_geode->addDrawable(m_geometry);

	m_node->addChild(m_geode);
	m_node->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
	m_node->setName("fenceGroup");

}

void FenceView::updateFenceGap(osg::Vec3 lastPosition, osg::Vec3 position)
{
	if (m_coordinates->size() > 1) {
		m_coordinates->at(m_coordinates->size() - 2) = osg::Vec3(position.x(), position.y(), position.z());
		m_coordinates->at(m_coordinates->size() - 1) = osg::Vec3(position.x(), position.y(), position.z() + m_fenceHeight);
		m_relativeHeights->at(m_relativeHeights->size() - 2) = 0.f;
		m_relativeHeights->at(m_relativeHeights->size() - 1) = 1.f;
	}
}

void FenceView::initializeShader()
{
	osg::ref_ptr<osg::StateSet> NodeState = m_node->getOrCreateStateSet();
	osg::Uniform* fenceColorU = new osg::Uniform("fenceColor", m_playerColor);
	NodeState->addUniform(fenceColorU);

	osg::Uniform* modelIDU = new osg::Uniform("modelID", GLOW);
	NodeState->addUniform(modelIDU);

	NodeState->setMode(GL_BLEND, osg::StateAttribute::ON);
	NodeState->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
	NodeState->setAttributeAndModes(shaders::m_allShaderPrograms[shaders::FENCE], osg::StateAttribute::ON);

	shaders::m_allShaderPrograms[shaders::FENCE]->addBindAttribLocation("a_relHeight", 5);
}

void FenceView::addFencePart(osg::Vec3 lastPosition, osg::Vec3 currentPosition)
{
	if (m_coordinates->size() == 0)
	{
		m_coordinates->push_back(lastPosition);
		m_coordinates->push_back(osg::Vec3(lastPosition.x(), lastPosition.y(), lastPosition.z() + m_fenceHeight));
		m_relativeHeights->push_back(0.f);
		m_relativeHeights->push_back(1.f);
	}

	m_coordinates->push_back(currentPosition);
	m_coordinates->push_back(osg::Vec3(currentPosition.x(), currentPosition.y(), currentPosition.z() + m_fenceHeight));
	m_relativeHeights->push_back(0.f);
	m_relativeHeights->push_back(1.f);

	enforceFencePartsLimit();

	// TODO
	// remove if no disadvantages seem necessary?
	// m_geometry->dirtyBound();
	m_drawArrays->setCount(m_coordinates->size());
}

void FenceView::removeAllFences()
{
	m_node->removeChild(m_geode);
	initializeFence();
}

void FenceView::enforceFencePartsLimit()
{
	int maxFenceParts = m_fenceController->getFenceLimit();

	// the quad strip contains two more vertices for the beginning of the fence
	int currentFenceParts = (m_coordinates->size() - 2) / 2;

	if (maxFenceParts != 0 && currentFenceParts > maxFenceParts)
	{
		for (int i = 0; i < (currentFenceParts - maxFenceParts); i++)
			removeFirstFencePart();
	}
}

void FenceView::removeFirstFencePart()
{
	m_coordinates->erase(m_coordinates->begin(), m_coordinates->begin() + 2);
	m_relativeHeights->erase(m_relativeHeights->begin(), m_relativeHeights->begin() + 2);
}
<commit_msg>avoid time-intensive array resizing in fence view<commit_after>#include "fenceview.h"
// OSG
#include <osg/ShapeDrawable>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Vec4>
#include <osg/PositionAttitudeTransform>
#include <osg/ref_ptr>

// troen
#include "../constants.h"
#include "shaders.h"
#include "../model/fencemodel.h"
#include "../controller/fencecontroller.h"

using namespace troen;

FenceView::FenceView(FenceController* fenceController, osg::Vec3 color, std::shared_ptr<AbstractModel>& model)
{
	AbstractView();
	m_playerColor = color;
	m_model = std::static_pointer_cast<FenceModel>(model);
	m_node = new osg::Group();

	m_fenceController = fenceController;

	initializeFence();
	initializeShader();
}

void FenceView::initializeFence()
{
	m_fenceHeight = FENCE_HEIGHT_VIEW;

	m_coordinates = new osg::Vec3Array();
	m_coordinates->setDataVariance(osg::Object::DYNAMIC);

	m_relativeHeights = new osg::FloatArray();
	m_relativeHeights->setDataVariance(osg::Object::DYNAMIC);

	// this value could need adaption; will avoid time-intensive array resizing
	m_coordinates->reserveArray(10000);
	m_relativeHeights->reserveArray(10000);

	m_geometry = new osg::Geometry();
	m_geometry->setVertexArray(m_coordinates);

	// set the relative height between 0 and 1 as an additional vertex attribute
	m_geometry->setVertexAttribArray(5, m_relativeHeights);
	m_geometry->setVertexAttribBinding(5, osg::Geometry::BIND_PER_VERTEX);

	// seems to be important so that we won't crash after 683 fence parts
	m_geometry->setUseDisplayList(false);

	// use the shared normal array.
	// polyGeom->setNormalArray(shared_normals.get(), osg::Array::BIND_OVERALL);

	m_drawArrays = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP, 0, 0);
	m_geometry->addPrimitiveSet(m_drawArrays);

	m_geode = new osg::Geode();
	m_geode->addDrawable(m_geometry);

	m_node->addChild(m_geode);
	m_node->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
	m_node->setName("fenceGroup");

}

void FenceView::updateFenceGap(osg::Vec3 lastPosition, osg::Vec3 position)
{
	if (m_coordinates->size() > 1) {
		m_coordinates->at(m_coordinates->size() - 2) = osg::Vec3(position.x(), position.y(), position.z());
		m_coordinates->at(m_coordinates->size() - 1) = osg::Vec3(position.x(), position.y(), position.z() + m_fenceHeight);
		m_relativeHeights->at(m_relativeHeights->size() - 2) = 0.f;
		m_relativeHeights->at(m_relativeHeights->size() - 1) = 1.f;
	}
}

void FenceView::initializeShader()
{
	osg::ref_ptr<osg::StateSet> NodeState = m_node->getOrCreateStateSet();
	osg::Uniform* fenceColorU = new osg::Uniform("fenceColor", m_playerColor);
	NodeState->addUniform(fenceColorU);

	osg::Uniform* modelIDU = new osg::Uniform("modelID", GLOW);
	NodeState->addUniform(modelIDU);

	NodeState->setMode(GL_BLEND, osg::StateAttribute::ON);
	NodeState->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
	NodeState->setAttributeAndModes(shaders::m_allShaderPrograms[shaders::FENCE], osg::StateAttribute::ON);

	shaders::m_allShaderPrograms[shaders::FENCE]->addBindAttribLocation("a_relHeight", 5);
}

void FenceView::addFencePart(osg::Vec3 lastPosition, osg::Vec3 currentPosition)
{
	if (m_coordinates->size() == 0)
	{
		m_coordinates->push_back(lastPosition);
		m_coordinates->push_back(osg::Vec3(lastPosition.x(), lastPosition.y(), lastPosition.z() + m_fenceHeight));
		m_relativeHeights->push_back(0.f);
		m_relativeHeights->push_back(1.f);
	}

	m_coordinates->push_back(currentPosition);
	m_coordinates->push_back(osg::Vec3(currentPosition.x(), currentPosition.y(), currentPosition.z() + m_fenceHeight));
	m_relativeHeights->push_back(0.f);
	m_relativeHeights->push_back(1.f);

	enforceFencePartsLimit();

	// TODO
	// remove if no disadvantages seem necessary?
	// m_geometry->dirtyBound();
	m_drawArrays->setCount(m_coordinates->size());

}

void FenceView::removeAllFences()
{
	m_node->removeChild(m_geode);
	initializeFence();
}

void FenceView::enforceFencePartsLimit()
{
	int maxFenceParts = m_fenceController->getFenceLimit();

	// the quad strip contains two more vertices for the beginning of the fence
	int currentFenceParts = (m_coordinates->size() - 2) / 2;

	if (maxFenceParts != 0 && currentFenceParts > maxFenceParts)
	{
		for (int i = 0; i < (currentFenceParts - maxFenceParts); i++)
			removeFirstFencePart();

		std::cout << "currentFenceParts: " << currentFenceParts << std::endl;
	}
}

void FenceView::removeFirstFencePart()
{
	m_coordinates->erase(m_coordinates->begin(), m_coordinates->begin() + 2);
	m_relativeHeights->erase(m_relativeHeights->begin(), m_relativeHeights->begin() + 2);
}
<|endoftext|>


<commit_before>#include "interfaz.h"

void Interfaz::vBienvenida()
{
	cout << "!Bienvenido al Sistema de Matricula!";
	Sleep(2500);
	system("cls");
}

char Interfaz::vMenuPrincipal()
{
	char ans;
	cout << "**************MENU PRINCIPAL**************" << endl;
	cout << "(1)--Informacion acerca de la Universidad" << endl;
	cout << "(2)--Lista de Escuelas" << endl;
	cout << "(3)--Lista de Cursos" << endl;
	cout << "(4)--Ajustes" << endl;
	cout << "(5)--Salir" << endl;
	cout << "******************************************" << endl;

	ans = _getch();

	while (ans < '1' || ans > '5')
	{
		cout << "Opcion Incorrecta. Try again " << endl;
		ans = _getch();
	}

	system("cls");
	return ans;
}

char Interfaz::vDatosPrimeraVez(Universidad* U)
{
	if (U->getNombre() == "Undefined")
	{
		cout << "!Hola!" << endl;
		cout << "Parece que es la primera vez que ingresas al sistema." << endl;
		cout << "?Deseas ingresar ahora los datos de la Universidad?";
		return vInfoConfirmacion();
	}
	return 0;
}

char Interfaz::vMenuAjustes(Universidad* U) //Estoy seguro que puede mejorarse mil veces
{
	char ans;

	if (U->getNombre() == "Undefined")
	{
		cout << "-(1)-Ingresar nombre de la Universidad" << endl;

		if (U->getNumero() == "Undefined")
			cout << "-(2)-Ingresar Numero de Telefono de la Universidad" << endl;
		else
			cout << "-(2)-Cambiar Numero de Telefono de la Universidad" << endl;
		if (U->getDireccion() == "Undefined")
			cout << "-(3)-Ingresar Direccion de la Universidad" << endl;
		else
			cout << "-(3)-Cambiar Direccion de la Universidad" << endl;

		cout << "-(4)-Salir" << endl;

		ans = _getch();

		while (ans < '1' || ans > '4')
		{
			cout << "Opcion Incorrecta. Try again " << endl;
			ans = _getch();
		}
	}
	else
	{
		if (U->getNumero() == "Undefined")
			cout << "-(1)-Ingresar Numero de Telefono de la Universidad" << endl;
		else
			cout << "-(1)-Cambiar Numero de Telefono de la Universidad" << endl;
		if (U->getDireccion() == "Undefined")
			cout << "-(2)-Ingresar Direccion de la Universidad" << endl;
		else
			cout << "-(2)-Cambiar Direccion de la Universidad" << endl;

		cout << "-(3)-Ingresar Escuela" << endl;
		cout << "-(4)-Ingresar Curso" << endl;
		cout << "-(5)-Eliminar Curso" << endl;
		cout << "-(6)-Salir" << endl;

		ans = _getch();

		while (ans < '1' || ans > '6')
		{
			cout << "Opcion Incorrecta. Try again " << endl;
			ans = _getch();
		}
	}

	system("cls");
	return ans;
}

void Interfaz::vIngresarNumero(Universidad* U)
{
	char ans;

	do
	{
		Sleep(500);
		cout << "Ingrese el numero de telefono -> "; string numero;
		std::cin >> numero; cin.ignore();

		while (chequeaNumero(numero) == false) //No le permite al usuario ingresar un algo que no sean numeros
		{
			cout << "Numero Invalido. Intente de nuevo";
			Sleep(800);
			system("cls");
			cout << string("Ingrese el numero de telefono -> "); cin.clear();
			std::cin >> numero; cin.ignore();
		}

		cout << endl << endl;
		cout << "Numero : " << "\"" << numero << "\" "; cout << "| es esta informacion correcta?";

		ans = vInfoConfirmacion();

		if (ans == 'S')
		{
			U->setTelefono(numero);
			msjPerfecto();
		}

	} while (ans == 'N');
}

void Interfaz::vIngresarDireccion(Universidad* U)
{
	char ans;

	do
	{
		Sleep(500);
		cout << "Ingrese la direccion -> "; string direccion; getline(std::cin, direccion); cout << endl << endl;
		cout << "Direccion : " << "\"" << direccion << "\" "; cout << "| es esta informacion correcta?";

		ans = vInfoConfirmacion();

		if (ans == 'S')
		{
			U->setDireccion(direccion);
			msjPerfecto();
		}

	} while (ans == 'N');
}

void Interfaz::vIngresarNombre(Universidad* U)
{
	char ans;
	do //Pide los datos al usuario y le da la opcion de cambiarlos las veces que quiera mientras no confirme su opcion
	{
		Sleep(500);
		cout << string("Ingrese el nombre de la Universidad -> "); string nombre; std::getline(std::cin, nombre); cout << endl << endl;

		cout << "Universidad : " << "\"" << nombre << "\" "; cout << "| es esta informacion correcta? (El nombre no se puede cambiar una vez confirmado)";

		ans = vInfoConfirmacion();

		while (nombre == "Undefined" || nombre == " " || nombre == "")
		{
			cout << "Nombre Invalido. Intente de nuevo -> ";
			Sleep(800);
			system("cls");
			cout << "Ingrese el nombre de la Universidad  -> "; std::getline(std::cin, nombre); cout << endl << endl;
		}

		if (ans == 'S') //Solo ingresa al nombre si el usuario confirma
		{
			U->setNombre(nombre);
			msjPerfecto();
		}

	} while (ans == 'N');
}

char Interfaz::vInfoConfirmacion()
{
	char ans;

	cout << endl << string(" SI (S) NO (N)") << endl;

	ans = toupper(_getch());

	while (ans != 'S' && ans != 'N') //Impide ingresar un valor diferente a S o N
	{
		ans = toupper(_getch());
	}

	system("cls");

	return ans;
}

void Interfaz::vIngresaEscuela(Universidad* U)
{
	string nombre;
	cout << "Ingrese el nombre de la escuela -> "; getline(cin, nombre); cout << endl;

	cout << "Escuela de : " << "\"" << nombre << "\" "; cout << "| es esta informacion correcta? (El nombre no se puede cambiar una vez confirmado)";

	char ans = vInfoConfirmacion();

	while (nombre == "Undefined" || nombre == " " || nombre == "")
	{
		cout << "Nombre Invalido. Intente de nuevo -> ";
		Sleep(800);
		system("cls");
		cout << "Ingrese el nombre de la escuela  -> "; std::getline(std::cin, nombre); cout << endl << endl;
	}

	Escuela* escu = new Escuela(nombre);

	U->getContenedorEscuelas()->insertaralInicio(escu);
	system("cls");
}

void Interfaz::vIngresaCurso(Universidad* U)
{

	cout << "Nombre de la Universidad: " << U->getNombre() << endl << endl;
	cout << U->getContenedorEscuelas()->toString('1') << endl;

	cout << "Digite las siglas de la Escuela a la que desea ingresar el curso -> ";
	string sigla; cin >> sigla;
	string aux;

	for (int i = 0; i < sigla.length(); i++)
	{
		aux += toupper(sigla[i]);
	}

	while (U->getContenedorEscuelas()->encuentraEscuela(aux) == false)
	{
		cin.clear();
		cout << "Escuela invalida. Favor digite una de las opciones dadas." << endl;
		cout << "-> ";
		cin >> sigla; aux = "";

		for (int i = 0; i < sigla.length(); i++)
		{
			aux += toupper(sigla[i]);
		}

	}

	system("cls");
	cin.ignore();
	string nombre;
	cout << "Ingrese el nombre del curso -> "; getline(cin, nombre); cout << endl;

	cout << "Curso: " << "\"" << nombre << "\" "; cout << "| es esta informacion correcta? ";

	char ans = vInfoConfirmacion();

	while (nombre == "Undefined" || nombre == " " || nombre == "")
	{
		cout << "Nombre Invalido. Intente de nuevo -> ";
		Sleep(800);
		system("cls");
		cout << "Ingrese el nombre del curso  -> "; std::getline(std::cin, nombre); cout << endl << endl;
	}

	Curso* cur = new Curso(nombre, U->getContenedorEscuelas()->retornaEscuelaEspecifica(aux)->getSiglaEscuela());

	U->getContenedorEscuelas()->retornaEscuelaEspecifica(aux)->insertarCurso(cur);

	msjPerfecto();

	system("cls");
}

void Interfaz::vEliminaCurso(Universidad *U) //debe implementarse mejor
{
	U->getContenedorEscuelas()->toString('2');

	cout << "Ingrese el codigo del curso que desea eliminar -> "; string codigo, sigla;

	cin >> codigo;

	if (codigo.length() < 3)
	{
		for (int i = 0; i < codigo.length(); i++)
		{
			sigla += codigo[i];
		}
	}

	else
	{

		for (int i = 0; i < 3; i++)
		{
			sigla += codigo[i];
		}
	}

	if (U->getContenedorEscuelas()->retornaEscuelaEspecifica(sigla)->retornaContenedorCursos()->eliminaCursoEspecifico(codigo))
		cout << "Curso eliminado con exito" << endl;
	else
		cout << "No se ha podido eliminar el curso." << endl;
}

bool Interfaz::chequeaNumero(string num)
{
	bool esNumero;

	for (size_t x = 0; x < num.length(); x++)
	{
		if (isdigit(num[x]))
			esNumero = true;
		else
		{
			esNumero = false;
			return esNumero;
		}
	}
	return esNumero;
}

void Interfaz::msjPerfecto()
{
	cout << endl << string("Perfecto!");
	Sleep(1500);
	system("cls");
}

void Interfaz::msjPausa()
{
	cout << "Presione cualquier tecla para continuar..." << endl;
	_getch();
}

void Interfaz::vtoString(Universidad* U) //Modificar para que sirva de informacion actual del sistema de matricula
{
	if (U->getNombre() == "Undefined" && U->getNumero() == "Undefined")
		cout << "Ups... parece que no se han ingresado todos los datos de la Universidad. Ve a Ajustes para agregarlos." << endl;
	else
		cout << U->toString() << endl;

	msjPausa();
	system("cls");
}

void Interfaz::vtoStringEscuelas(Universidad* U, char op)
{
	if (U->getNombre() == "Undefined")
		cout << "No se ha ingresado el nombre de la Universidad. Vaya a Ajustes." << endl;
	else
	{
		cout << "Nombre de la Universidad: " << U->getNombre() << endl << endl;
		cout << U->getContenedorEscuelas()->toString(op) << endl;
	}
	msjPausa();
	system("cls");
}

<commit_msg>faltaba un cout para correr el tostring lelel<commit_after>#include "interfaz.h"

void Interfaz::vBienvenida()
{
	cout << "!Bienvenido al Sistema de Matricula!";
	Sleep(2500);
	system("cls");
}

char Interfaz::vMenuPrincipal()
{
	char ans;
	cout << "**************MENU PRINCIPAL**************" << endl;
	cout << "(1)--Informacion acerca de la Universidad" << endl;
	cout << "(2)--Lista de Escuelas" << endl;
	cout << "(3)--Lista de Cursos" << endl;
	cout << "(4)--Ajustes" << endl;
	cout << "(5)--Salir" << endl;
	cout << "******************************************" << endl;

	ans = _getch();

	while (ans < '1' || ans > '5')
	{
		cout << "Opcion Incorrecta. Try again " << endl;
		ans = _getch();
	}

	system("cls");
	return ans;
}

char Interfaz::vDatosPrimeraVez(Universidad* U)
{
	if (U->getNombre() == "Undefined")
	{
		cout << "!Hola!" << endl;
		cout << "Parece que es la primera vez que ingresas al sistema." << endl;
		cout << "?Deseas ingresar ahora los datos de la Universidad?";
		return vInfoConfirmacion();
	}
	return 0;
}

char Interfaz::vMenuAjustes(Universidad* U) //Estoy seguro que puede mejorarse mil veces
{
	char ans;

	if (U->getNombre() == "Undefined")
	{
		cout << "-(1)-Ingresar nombre de la Universidad" << endl;

		if (U->getNumero() == "Undefined")
			cout << "-(2)-Ingresar Numero de Telefono de la Universidad" << endl;
		else
			cout << "-(2)-Cambiar Numero de Telefono de la Universidad" << endl;
		if (U->getDireccion() == "Undefined")
			cout << "-(3)-Ingresar Direccion de la Universidad" << endl;
		else
			cout << "-(3)-Cambiar Direccion de la Universidad" << endl;

		cout << "-(4)-Salir" << endl;

		ans = _getch();

		while (ans < '1' || ans > '4')
		{
			cout << "Opcion Incorrecta. Try again " << endl;
			ans = _getch();
		}
	}
	else
	{
		if (U->getNumero() == "Undefined")
			cout << "-(1)-Ingresar Numero de Telefono de la Universidad" << endl;
		else
			cout << "-(1)-Cambiar Numero de Telefono de la Universidad" << endl;
		if (U->getDireccion() == "Undefined")
			cout << "-(2)-Ingresar Direccion de la Universidad" << endl;
		else
			cout << "-(2)-Cambiar Direccion de la Universidad" << endl;

		cout << "-(3)-Ingresar Escuela" << endl;
		cout << "-(4)-Ingresar Curso" << endl;
		cout << "-(5)-Eliminar Curso" << endl;
		cout << "-(6)-Salir" << endl;

		ans = _getch();

		while (ans < '1' || ans > '6')
		{
			cout << "Opcion Incorrecta. Try again " << endl;
			ans = _getch();
		}
	}

	system("cls");
	return ans;
}

void Interfaz::vIngresarNumero(Universidad* U)
{
	char ans;

	do
	{
		Sleep(500);
		cout << "Ingrese el numero de telefono -> "; string numero;
		std::cin >> numero; cin.ignore();

		while (chequeaNumero(numero) == false) //No le permite al usuario ingresar un algo que no sean numeros
		{
			cout << "Numero Invalido. Intente de nuevo";
			Sleep(800);
			system("cls");
			cout << string("Ingrese el numero de telefono -> "); cin.clear();
			std::cin >> numero; cin.ignore();
		}

		cout << endl << endl;
		cout << "Numero : " << "\"" << numero << "\" "; cout << "| es esta informacion correcta?";

		ans = vInfoConfirmacion();

		if (ans == 'S')
		{
			U->setTelefono(numero);
			msjPerfecto();
		}

	} while (ans == 'N');
}

void Interfaz::vIngresarDireccion(Universidad* U)
{
	char ans;

	do
	{
		Sleep(500);
		cout << "Ingrese la direccion -> "; string direccion; getline(std::cin, direccion); cout << endl << endl;
		cout << "Direccion : " << "\"" << direccion << "\" "; cout << "| es esta informacion correcta?";

		ans = vInfoConfirmacion();

		if (ans == 'S')
		{
			U->setDireccion(direccion);
			msjPerfecto();
		}

	} while (ans == 'N');
}

void Interfaz::vIngresarNombre(Universidad* U)
{
	char ans;
	do //Pide los datos al usuario y le da la opcion de cambiarlos las veces que quiera mientras no confirme su opcion
	{
		Sleep(500);
		cout << string("Ingrese el nombre de la Universidad -> "); string nombre; std::getline(std::cin, nombre); cout << endl << endl;

		cout << "Universidad : " << "\"" << nombre << "\" "; cout << "| es esta informacion correcta? (El nombre no se puede cambiar una vez confirmado)";

		ans = vInfoConfirmacion();

		while (nombre == "Undefined" || nombre == " " || nombre == "")
		{
			cout << "Nombre Invalido. Intente de nuevo -> ";
			Sleep(800);
			system("cls");
			cout << "Ingrese el nombre de la Universidad  -> "; std::getline(std::cin, nombre); cout << endl << endl;
		}

		if (ans == 'S') //Solo ingresa al nombre si el usuario confirma
		{
			U->setNombre(nombre);
			msjPerfecto();
		}

	} while (ans == 'N');
}

char Interfaz::vInfoConfirmacion()
{
	char ans;

	cout << endl << string(" SI (S) NO (N)") << endl;

	ans = toupper(_getch());

	while (ans != 'S' && ans != 'N') //Impide ingresar un valor diferente a S o N
	{
		ans = toupper(_getch());
	}

	system("cls");

	return ans;
}

void Interfaz::vIngresaEscuela(Universidad* U)
{
	string nombre;
	cout << "Ingrese el nombre de la escuela -> "; getline(cin, nombre); cout << endl;

	cout << "Escuela de : " << "\"" << nombre << "\" "; cout << "| es esta informacion correcta? (El nombre no se puede cambiar una vez confirmado)";

	char ans = vInfoConfirmacion();

	while (nombre == "Undefined" || nombre == " " || nombre == "")
	{
		cout << "Nombre Invalido. Intente de nuevo -> ";
		Sleep(800);
		system("cls");
		cout << "Ingrese el nombre de la escuela  -> "; std::getline(std::cin, nombre); cout << endl << endl;
	}

	Escuela* escu = new Escuela(nombre);

	U->getContenedorEscuelas()->insertaralInicio(escu);
	system("cls");
}

void Interfaz::vIngresaCurso(Universidad* U)
{

	cout << "Nombre de la Universidad: " << U->getNombre() << endl << endl;
	cout << U->getContenedorEscuelas()->toString('1') << endl;

	cout << "Digite las siglas de la Escuela a la que desea ingresar el curso -> ";
	string sigla; cin >> sigla;
	string aux;

	for (int i = 0; i < sigla.length(); i++)
	{
		aux += toupper(sigla[i]);
	}

	while (U->getContenedorEscuelas()->encuentraEscuela(aux) == false)
	{
		cin.clear();
		cout << "Escuela invalida. Favor digite una de las opciones dadas." << endl;
		cout << "-> ";
		cin >> sigla; aux = "";

		for (int i = 0; i < sigla.length(); i++)
		{
			aux += toupper(sigla[i]);
		}

	}

	system("cls");
	cin.ignore();
	string nombre;
	cout << "Ingrese el nombre del curso -> "; getline(cin, nombre); cout << endl;

	cout << "Curso: " << "\"" << nombre << "\" "; cout << "| es esta informacion correcta? ";

	char ans = vInfoConfirmacion();

	while (nombre == "Undefined" || nombre == " " || nombre == "")
	{
		cout << "Nombre Invalido. Intente de nuevo -> ";
		Sleep(800);
		system("cls");
		cout << "Ingrese el nombre del curso  -> "; std::getline(std::cin, nombre); cout << endl << endl;
	}

	Curso* cur = new Curso(nombre, U->getContenedorEscuelas()->retornaEscuelaEspecifica(aux)->getSiglaEscuela());

	U->getContenedorEscuelas()->retornaEscuelaEspecifica(aux)->insertarCurso(cur);

	msjPerfecto();

	system("cls");
}

void Interfaz::vEliminaCurso(Universidad *U) //debe implementarse mejor
{
	cout << U->getContenedorEscuelas()->toString('2') << endl;

	cout << "Ingrese el codigo del curso que desea eliminar -> "; string codigo, sigla;

	cin >> codigo;

	if (codigo.length() < 3)
	{
		for (int i = 0; i < codigo.length(); i++)
		{
			sigla += codigo[i];
		}
	}

	else
	{

		for (int i = 0; i < 3; i++)
		{
			sigla += codigo[i];
		}
	}

	if (U->getContenedorEscuelas()->retornaEscuelaEspecifica(sigla)->retornaContenedorCursos()->eliminaCursoEspecifico(codigo))
		cout << "Curso eliminado con exito" << endl;
	else
		cout << "No se ha podido eliminar el curso." << endl;
}

bool Interfaz::chequeaNumero(string num)
{
	bool esNumero;

	for (size_t x = 0; x < num.length(); x++)
	{
		if (isdigit(num[x]))
			esNumero = true;
		else
		{
			esNumero = false;
			return esNumero;
		}
	}
	return esNumero;
}

void Interfaz::msjPerfecto()
{
	cout << endl << string("Perfecto!");
	Sleep(1500);
	system("cls");
}

void Interfaz::msjPausa()
{
	cout << "Presione cualquier tecla para continuar..." << endl;
	_getch();
}

void Interfaz::vtoString(Universidad* U) //Modificar para que sirva de informacion actual del sistema de matricula
{
	if (U->getNombre() == "Undefined" && U->getNumero() == "Undefined")
		cout << "Ups... parece que no se han ingresado todos los datos de la Universidad. Ve a Ajustes para agregarlos." << endl;
	else
		cout << U->toString() << endl;

	msjPausa();
	system("cls");
}

void Interfaz::vtoStringEscuelas(Universidad* U, char op)
{
	if (U->getNombre() == "Undefined")
		cout << "No se ha ingresado el nombre de la Universidad. Vaya a Ajustes." << endl;
	else
	{
		cout << "Nombre de la Universidad: " << U->getNombre() << endl << endl;
		cout << U->getContenedorEscuelas()->toString(op) << endl;
	}
	msjPausa();
	system("cls");
}

<|endoftext|>


<commit_before>#include <x0/buffer.hpp>

#include <x0/source.hpp>
#include <x0/fd_source.hpp>
#include <x0/file_source.hpp>
#include <x0/buffer_source.hpp>
#include <x0/filter_source.hpp>
#include <x0/composite_source.hpp>

#include <x0/sink.hpp>
#include <x0/fd_sink.hpp>
#include <x0/file_sink.hpp>
#include <x0/buffer_sink.hpp>

#include <x0/filter.hpp>

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>

#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cassert>
#include <strings.h>
#include <unistd.h>

class io_test :
	public CPPUNIT_NS::TestFixture
{
public:
	CPPUNIT_TEST_SUITE(io_test);
		// source
		CPPUNIT_TEST(test_buffer_source);
		CPPUNIT_TEST(test_fd_source);
		CPPUNIT_TEST(test_file_source);
		CPPUNIT_TEST(test_filter_source);
		CPPUNIT_TEST(test_composite_source);

		// sink
		CPPUNIT_TEST(test_buffer_sink);
		CPPUNIT_TEST(test_fd_sink);
		CPPUNIT_TEST(test_file_sink);
	CPPUNIT_TEST_SUITE_END();

private:
	void test_buffer_source()
	{
		x0::buffer_source s(x0::buffer("hello"));

		x0::buffer output;
		x0::buffer_ref ref = s.pull(output);

		CPPUNIT_ASSERT(output == "hello");
		CPPUNIT_ASSERT(ref == output);
	}

	void test_fd_source()
	{
		int pfd[2];
		int rv = pipe2(pfd, O_NONBLOCK);
		CPPUNIT_ASSERT(rv != -1);
		x0::fd_source in(pfd[0]);
		x0::buffer output;

		::write(pfd[1], "12345", 5);
		CPPUNIT_ASSERT(in.pull(output) == "12345");
		CPPUNIT_ASSERT(output == "12345");

		::write(pfd[1], "abcd", 4);
		CPPUNIT_ASSERT(in.pull(output) == "abcd");
		CPPUNIT_ASSERT(output == "12345abcd");

		CPPUNIT_ASSERT(in.pull(output) == "");
	}

	void test_file_source()
	{
		using namespace x0;

		fileinfo_ptr info(new fileinfo(__FILE__));
		file_ptr infile(new file(info, O_RDONLY));
		CPPUNIT_ASSERT(infile->handle() != -1);

		file_source in(infile);
		buffer_sink out;

		while (in.pump(out)) ;

		CPPUNIT_ASSERT(!out.buffer().empty());
	}

	void test_filter_source()
	{
		//! \todo
	}

	void test_composite_source()
	{
		using namespace x0;

		composite_source s;
		s.push_back(source_ptr(new buffer_source(const_buffer("hello"))));
		s.push_back(source_ptr(new buffer_source(buffer(", "))));
		s.push_back(source_ptr(new buffer_source(buffer("world"))));

		buffer output;
		CPPUNIT_ASSERT(s.pull(output) == "hello");
		CPPUNIT_ASSERT(s.pull(output) == ", ");
		CPPUNIT_ASSERT(s.pull(output) == "world");
		CPPUNIT_ASSERT(!s.pull(output));
		CPPUNIT_ASSERT(output == "hello, world");
	}

	void test_buffer_sink()
	{
		using namespace x0;

		buffer_source src(const_buffer("Hello World!"));
		buffer_sink snk;
		src.pump(snk);

		CPPUNIT_ASSERT(snk.buffer() == "Hello World!");
	}

	void test_fd_sink()
	{
		//! \todo
	}

	void test_file_sink()
	{
		//! \todo
	}

private:
private: // {{{ debug helper
	void print(const x0::buffer& b, const char *msg = 0)
	{
		if (msg && *msg)
			printf("buffer(%s): '%s'\n", msg, b.str().c_str());
		else
			printf("buffer: '%s'\n", b.str().c_str());
	}

	void print(const x0::buffer_ref& v, const char *msg = 0)
	{
		char prefix[64];
		if (msg && *msg)
			snprintf(prefix, sizeof(prefix), "buffer.view(%s)", msg);
		else
			snprintf(prefix, sizeof(prefix), "buffer.view");

		if (v)
			printf("%s: '%s' (offset=%ld, size=%ld)\n",
				prefix, v.str().c_str(), v.offset(), v.size());
		else
			printf("%s: NULL\n", prefix);
	}
	//}}}
};

CPPUNIT_TEST_SUITE_REGISTRATION(io_test);
<commit_msg>tests: added assert(errno == EAGAIN)<commit_after>#include <x0/buffer.hpp>

#include <x0/source.hpp>
#include <x0/fd_source.hpp>
#include <x0/file_source.hpp>
#include <x0/buffer_source.hpp>
#include <x0/filter_source.hpp>
#include <x0/composite_source.hpp>

#include <x0/sink.hpp>
#include <x0/fd_sink.hpp>
#include <x0/file_sink.hpp>
#include <x0/buffer_sink.hpp>

#include <x0/filter.hpp>

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>

#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cassert>
#include <strings.h>
#include <unistd.h>

class io_test :
	public CPPUNIT_NS::TestFixture
{
public:
	CPPUNIT_TEST_SUITE(io_test);
		// source
		CPPUNIT_TEST(test_buffer_source);
		CPPUNIT_TEST(test_fd_source);
		CPPUNIT_TEST(test_file_source);
		CPPUNIT_TEST(test_filter_source);
		CPPUNIT_TEST(test_composite_source);

		// sink
		CPPUNIT_TEST(test_buffer_sink);
		CPPUNIT_TEST(test_fd_sink);
		CPPUNIT_TEST(test_file_sink);
	CPPUNIT_TEST_SUITE_END();

private:
	void test_buffer_source()
	{
		x0::buffer_source s(x0::buffer("hello"));

		x0::buffer output;
		x0::buffer_ref ref = s.pull(output);

		CPPUNIT_ASSERT(output == "hello");
		CPPUNIT_ASSERT(ref == output);
	}

	void test_fd_source()
	{
		int pfd[2];
		int rv = pipe2(pfd, O_NONBLOCK);
		CPPUNIT_ASSERT(rv != -1);
		x0::fd_source in(pfd[0]);
		x0::buffer output;

		::write(pfd[1], "12345", 5);
		CPPUNIT_ASSERT(in.pull(output) == "12345");
		CPPUNIT_ASSERT(output == "12345");

		::write(pfd[1], "abcd", 4);
		CPPUNIT_ASSERT(in.pull(output) == "abcd");
		CPPUNIT_ASSERT(output == "12345abcd");

		CPPUNIT_ASSERT(in.pull(output) == "");
		CPPUNIT_ASSERT(errno == EAGAIN);
	}

	void test_file_source()
	{
		using namespace x0;

		fileinfo_ptr info(new fileinfo(__FILE__));
		file_ptr infile(new file(info, O_RDONLY));
		CPPUNIT_ASSERT(infile->handle() != -1);

		file_source in(infile);
		buffer_sink out;

		while (in.pump(out)) ;

		CPPUNIT_ASSERT(!out.buffer().empty());
	}

	void test_filter_source()
	{
		//! \todo
	}

	void test_composite_source()
	{
		using namespace x0;

		composite_source s;
		s.push_back(source_ptr(new buffer_source(const_buffer("hello"))));
		s.push_back(source_ptr(new buffer_source(buffer(", "))));
		s.push_back(source_ptr(new buffer_source(buffer("world"))));

		buffer output;
		CPPUNIT_ASSERT(s.pull(output) == "hello");
		CPPUNIT_ASSERT(s.pull(output) == ", ");
		CPPUNIT_ASSERT(s.pull(output) == "world");
		CPPUNIT_ASSERT(!s.pull(output));
		CPPUNIT_ASSERT(output == "hello, world");
	}

	void test_buffer_sink()
	{
		using namespace x0;

		buffer_source src(const_buffer("Hello World!"));
		buffer_sink snk;
		src.pump(snk);

		CPPUNIT_ASSERT(snk.buffer() == "Hello World!");
	}

	void test_fd_sink()
	{
		//! \todo
	}

	void test_file_sink()
	{
		//! \todo
	}

private:
private: // {{{ debug helper
	void print(const x0::buffer& b, const char *msg = 0)
	{
		if (msg && *msg)
			printf("buffer(%s): '%s'\n", msg, b.str().c_str());
		else
			printf("buffer: '%s'\n", b.str().c_str());
	}

	void print(const x0::buffer_ref& v, const char *msg = 0)
	{
		char prefix[64];
		if (msg && *msg)
			snprintf(prefix, sizeof(prefix), "buffer.view(%s)", msg);
		else
			snprintf(prefix, sizeof(prefix), "buffer.view");

		if (v)
			printf("%s: '%s' (offset=%ld, size=%ld)\n",
				prefix, v.str().c_str(), v.offset(), v.size());
		else
			printf("%s: NULL\n", prefix);
	}
	//}}}
};

CPPUNIT_TEST_SUITE_REGISTRATION(io_test);
<|endoftext|>


<commit_before>/*
* Covariant Script Parser
*
* Licensed under the Covariant Innovation General Public License,
* Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://covariant.cn/licenses/LICENSE-1.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.
*
* Copyright (C) 2019 Michael Lee(李登淳)
* Email: mikecovlee@163.com
* Github: https://github.com/mikecovlee
*/
#include <covscript/impl/compiler.hpp>

namespace cs {
	void compiler_type::kill_brackets(std::deque<token_base *> &tokens, std::size_t
	                                  line_num)
	{
		std::deque<token_base *> oldt;
		std::swap(tokens, oldt);
		tokens.clear();
		bool insert_vardef = false;
		bool insert_varchk = false;
		bool expected_fdef = false;
		bool expected_fcall = false;
		bool expected_lambda = false;
		for (auto &ptr:oldt) {
			switch (ptr->get_type()) {
			default:
				break;
			case token_types::action:
				expected_fcall = false;
				switch (static_cast<token_action *>(ptr)->get_action()) {
				default:
					break;
				case action_types::import_:
					insert_vardef = true;
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					continue;
				case action_types::var_:
					insert_varchk = true;
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::varchk_));
					continue;
				case action_types::constant_:
					insert_varchk = true;
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::varchk_));
					continue;
				case action_types::for_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::varprt_));
					continue;
				case action_types::foreach_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::varprt_));
					continue;
				case action_types::struct_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					continue;
				case action_types::function_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					expected_fdef = true;
					continue;
				case action_types::namespace_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					continue;
				case action_types::catch_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					continue;
				}
				break;
			case token_types::id:
				expected_fcall = true;
				break;
			case token_types::value:
				expected_fcall = false;
				break;
			case token_types::sblist: {
				for (auto &list:static_cast<token_sblist *>(ptr)->get_list())
					kill_brackets(list);
				if (expected_fcall) {
					std::deque<tree_type<token_base *>> tlist;
					if (expected_fdef) {
						expected_fdef = false;
						no_optimize = true;
					}
					for (auto &list:static_cast<token_sblist *>(ptr)->get_list()) {
						tree_type<token_base *> tree;
						gen_tree(tree, list);
						tlist.push_back(tree);
					}
					no_optimize = false;
					if (!expected_lambda)
						tokens.push_back(new token_signal(signal_types::fcall_));
					tokens.push_back(new token_arglist(tlist));
					continue;
				}
				else {
					expected_fcall = true;
					break;
				}
			}
			case token_types::mblist: {
				auto *mbl = static_cast<token_mblist *>(ptr);
				if (mbl->get_list().size() != 1)
					throw runtime_error("There are no more elements in middle bracket.");
				kill_brackets(mbl->get_list().front());
				tree_type<token_base *> tree;
				gen_tree(tree, mbl->get_list().front());
				tokens.push_back(new token_signal(signal_types::access_));
				tokens.push_back(new token_expr(tree));
				expected_fcall = true;
				continue;
			}
			case token_types::lblist: {
				for (auto &list:static_cast<token_lblist *>(ptr)->get_list())
					kill_brackets(list);
				std::deque<tree_type<token_base *>> tlist;
				for (auto &list:static_cast<token_lblist *>(ptr)->get_list()) {
					tree_type<token_base *> tree;
					gen_tree(tree, list);
					tlist.push_back(tree);
				}
				tokens.push_back(new token_array(tlist));
				expected_fcall = false;
				continue;
			}
			case token_types::signal: {
				switch (static_cast<token_signal *>(ptr)->get_signal()) {
				default:
					break;
				case signal_types::com_:
					if (insert_vardef) {
						tokens.push_back(ptr);
						tokens.push_back(new token_signal(signal_types::vardef_));
						continue;
					}
					else if (insert_varchk) {
						tokens.push_back(ptr);
						tokens.push_back(new token_signal(signal_types::varchk_));
						continue;
					}
					else
						break;
				case signal_types::arrow_:
					if (expected_lambda) {
						tokens.push_back(new token_signal(signal_types::lambda_, line_num));
						expected_lambda = false;
						expected_fcall = false;
						continue;
					}
					else
						break;
				case signal_types::esb_:
					if (expected_fcall) {
						if (!expected_lambda)
							tokens.push_back(new token_signal(signal_types::fcall_));
						tokens.push_back(new token_arglist());
					}
					else
						throw runtime_error("Do not allow standalone empty small parentheses.");
					expected_fcall = false;
					continue;
				case signal_types::emb_:
					expected_fcall = true;
					expected_lambda = true;
					tokens.push_back(ptr);
					continue;
				case signal_types::elb_:
					tokens.push_back(new token_array());
					expected_fcall = false;
					continue;
				}
				expected_lambda = false;
				expected_fcall = false;
				break;
			}
			}
			tokens.
			push_back(ptr);
		}
	}

	void compiler_type::split_token(std::deque<token_base *> &raw, std::deque<token_base *> &signals,
	                                std::deque<token_base *> &objects)
	{
		bool request_signal = false;
		for (auto &ptr:raw) {
			if (ptr->get_type() == token_types::action)
				throw runtime_error("Wrong format of expression.");
			if (ptr->get_type() == token_types::signal) {
				if (!request_signal)
					objects.push_back(nullptr);
				signals.push_back(ptr);
				request_signal = false;
			}
			else {
				objects.push_back(ptr);
				request_signal = true;
			}
		}
		if (!request_signal)
			objects.push_back(nullptr);
	}

	void compiler_type::build_tree(tree_type<token_base *> &tree, std::deque<token_base *> &signals,
	                               std::deque<token_base *> &objects)
	{
		if (objects.empty() || signals.empty() || objects.size() != signals.size() + 1)
			throw runtime_error("Wrong grammar.");
		for (auto &obj:objects) {
			if (obj != nullptr && obj->get_type() == token_types::sblist) {
				auto *sbl = static_cast<token_sblist *>(obj);
				std::deque<token_base *> tokens;
				for (auto &list:sbl->get_list()) {
					for (auto &it:list)
						tokens.push_back(it);
					tokens.push_back(new token_signal(signal_types::com_));
				}
				tokens.pop_back();
				tree_type<token_base *> t;
				gen_tree(t, tokens);
				obj = new token_expr(t);
			}
		}
		tree.clear();
		tree.emplace_root_left(tree.root(), signals.front());
		tree.emplace_left_left(tree.root(), objects.front());
		for (std::size_t i = 1; i < signals.size(); ++i) {
			for (typename tree_type<token_base *>::iterator it = tree.root(); it.usable(); it = it.right()) {
				if (!it.right().usable()) {
					tree.emplace_right_right(it, objects.at(i));
					break;
				}
			}
			for (typename tree_type<token_base *>::iterator it = tree.root(); it.usable(); it = it.right()) {
				if (!it.right().usable()) {
					tree.emplace_root_left(it, signals.at(i));
					break;
				}
				if (get_signal_level(it.data()) == get_signal_level(signals.at(i))) {
					if (is_left_associative(it.data()))
						tree.emplace_right_left(it, signals.at(i));
					else
						tree.emplace_root_left(it, signals.at(i));
					break;
				}
				if (get_signal_level(it.data()) > get_signal_level(signals.at(i))) {
					tree.emplace_root_left(it, signals.at(i));
					break;
				}
			}
		}
		for (typename tree_type<token_base *>::iterator it = tree.root(); it.usable(); it = it.right()) {
			if (!it.right().usable()) {
				tree.emplace_right_right(it, objects.back());
				break;
			}
		}
	}

	void compiler_type::gen_tree(tree_type<token_base *> &tree, std::deque<token_base *> &raw)
	{
		tree.clear();
		if (raw.size() == 1) {
			token_base *obj = raw.front();
			if (obj != nullptr && obj->get_type() == token_types::sblist) {
				auto *sbl = static_cast<token_sblist *>(obj);
				std::deque<token_base *> tokens;
				for (auto &list:sbl->get_list()) {
					for (auto &it:list)
						tokens.push_back(it);
					tokens.push_back(new token_signal(signal_types::com_));
				}
				tokens.pop_back();
				tree_type<token_base *> t;
				gen_tree(t, tokens);
				obj = new token_expr(t);
			}
			tree.emplace_root_left(tree.root(), obj);
		}
		else {
			std::deque<token_base *> signals, objects;
			split_token(raw, signals, objects);
			build_tree(tree, signals, objects);
		}
		optimize_expression(tree);
	}

	void compiler_type::kill_expr(std::deque<token_base *> &tokens)
	{
		std::deque<token_base *> oldt, expr;
		std::swap(tokens, oldt);
		tokens.clear();
		for (auto &ptr:oldt) {
			if (ptr->get_type() == token_types::action || ptr->get_type() == token_types::endline) {
				if (!expr.empty()) {
					tree_type<token_base *> tree;
					gen_tree(tree, expr);
					tokens.push_back(new token_expr(tree));
					expr.clear();
				}
				tokens.push_back(ptr);
			}
			else
				expr.push_back(ptr);
		}
	}
}
<commit_msg>Fix line num inserting<commit_after>/*
* Covariant Script Parser
*
* Licensed under the Covariant Innovation General Public License,
* Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://covariant.cn/licenses/LICENSE-1.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.
*
* Copyright (C) 2019 Michael Lee(李登淳)
* Email: mikecovlee@163.com
* Github: https://github.com/mikecovlee
*/
#include <covscript/impl/compiler.hpp>

namespace cs {
	void compiler_type::kill_brackets(std::deque<token_base *> &tokens, std::size_t
	                                  line_num)
	{
		std::deque<token_base *> oldt;
		std::swap(tokens, oldt);
		tokens.clear();
		bool insert_vardef = false;
		bool insert_varchk = false;
		bool expected_fdef = false;
		bool expected_fcall = false;
		bool expected_lambda = false;
		for (auto &ptr:oldt) {
			switch (ptr->get_type()) {
			default:
				break;
			case token_types::action:
				expected_fcall = false;
				switch (static_cast<token_action *>(ptr)->get_action()) {
				default:
					break;
				case action_types::import_:
					insert_vardef = true;
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					continue;
				case action_types::var_:
					insert_varchk = true;
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::varchk_));
					continue;
				case action_types::constant_:
					insert_varchk = true;
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::varchk_));
					continue;
				case action_types::for_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::varprt_));
					continue;
				case action_types::foreach_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::varprt_));
					continue;
				case action_types::struct_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					continue;
				case action_types::function_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					expected_fdef = true;
					continue;
				case action_types::namespace_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					continue;
				case action_types::catch_:
					tokens.push_back(ptr);
					tokens.push_back(new token_signal(signal_types::vardef_));
					continue;
				}
				break;
			case token_types::id:
				expected_fcall = true;
				break;
			case token_types::value:
				expected_fcall = false;
				break;
			case token_types::sblist: {
				for (auto &list:static_cast<token_sblist *>(ptr)->get_list())
					kill_brackets(list, line_num);
				if (expected_fcall) {
					std::deque<tree_type<token_base *>> tlist;
					if (expected_fdef) {
						expected_fdef = false;
						no_optimize = true;
					}
					for (auto &list:static_cast<token_sblist *>(ptr)->get_list()) {
						tree_type<token_base *> tree;
						gen_tree(tree, list);
						tlist.push_back(tree);
					}
					no_optimize = false;
					if (!expected_lambda)
						tokens.push_back(new token_signal(signal_types::fcall_));
					tokens.push_back(new token_arglist(tlist));
					continue;
				}
				else {
					expected_fcall = true;
					break;
				}
			}
			case token_types::mblist: {
				auto *mbl = static_cast<token_mblist *>(ptr);
				if (mbl->get_list().size() != 1)
					throw runtime_error("There are no more elements in middle bracket.");
				kill_brackets(mbl->get_list().front(), line_num);
				tree_type<token_base *> tree;
				gen_tree(tree, mbl->get_list().front());
				tokens.push_back(new token_signal(signal_types::access_));
				tokens.push_back(new token_expr(tree));
				expected_fcall = true;
				continue;
			}
			case token_types::lblist: {
				for (auto &list:static_cast<token_lblist *>(ptr)->get_list())
					kill_brackets(list, line_num);
				std::deque<tree_type<token_base *>> tlist;
				for (auto &list:static_cast<token_lblist *>(ptr)->get_list()) {
					tree_type<token_base *> tree;
					gen_tree(tree, list);
					tlist.push_back(tree);
				}
				tokens.push_back(new token_array(tlist));
				expected_fcall = false;
				continue;
			}
			case token_types::signal: {
				switch (static_cast<token_signal *>(ptr)->get_signal()) {
				default:
					break;
				case signal_types::com_:
					if (insert_vardef) {
						tokens.push_back(ptr);
						tokens.push_back(new token_signal(signal_types::vardef_));
						continue;
					}
					else if (insert_varchk) {
						tokens.push_back(ptr);
						tokens.push_back(new token_signal(signal_types::varchk_));
						continue;
					}
					else
						break;
				case signal_types::arrow_:
					if (expected_lambda) {
						tokens.push_back(new token_signal(signal_types::lambda_, line_num));
						expected_lambda = false;
						expected_fcall = false;
						continue;
					}
					else
						break;
				case signal_types::esb_:
					if (expected_fcall) {
						if (!expected_lambda)
							tokens.push_back(new token_signal(signal_types::fcall_));
						tokens.push_back(new token_arglist());
					}
					else
						throw runtime_error("Do not allow standalone empty small parentheses.");
					expected_fcall = false;
					continue;
				case signal_types::emb_:
					expected_fcall = true;
					expected_lambda = true;
					tokens.push_back(ptr);
					continue;
				case signal_types::elb_:
					tokens.push_back(new token_array());
					expected_fcall = false;
					continue;
				}
				expected_lambda = false;
				expected_fcall = false;
				break;
			}
			}
			tokens.
			push_back(ptr);
		}
	}

	void compiler_type::split_token(std::deque<token_base *> &raw, std::deque<token_base *> &signals,
	                                std::deque<token_base *> &objects)
	{
		bool request_signal = false;
		for (auto &ptr:raw) {
			if (ptr->get_type() == token_types::action)
				throw runtime_error("Wrong format of expression.");
			if (ptr->get_type() == token_types::signal) {
				if (!request_signal)
					objects.push_back(nullptr);
				signals.push_back(ptr);
				request_signal = false;
			}
			else {
				objects.push_back(ptr);
				request_signal = true;
			}
		}
		if (!request_signal)
			objects.push_back(nullptr);
	}

	void compiler_type::build_tree(tree_type<token_base *> &tree, std::deque<token_base *> &signals,
	                               std::deque<token_base *> &objects)
	{
		if (objects.empty() || signals.empty() || objects.size() != signals.size() + 1)
			throw runtime_error("Wrong grammar.");
		for (auto &obj:objects) {
			if (obj != nullptr && obj->get_type() == token_types::sblist) {
				auto *sbl = static_cast<token_sblist *>(obj);
				std::deque<token_base *> tokens;
				for (auto &list:sbl->get_list()) {
					for (auto &it:list)
						tokens.push_back(it);
					tokens.push_back(new token_signal(signal_types::com_));
				}
				tokens.pop_back();
				tree_type<token_base *> t;
				gen_tree(t, tokens);
				obj = new token_expr(t);
			}
		}
		tree.clear();
		tree.emplace_root_left(tree.root(), signals.front());
		tree.emplace_left_left(tree.root(), objects.front());
		for (std::size_t i = 1; i < signals.size(); ++i) {
			for (typename tree_type<token_base *>::iterator it = tree.root(); it.usable(); it = it.right()) {
				if (!it.right().usable()) {
					tree.emplace_right_right(it, objects.at(i));
					break;
				}
			}
			for (typename tree_type<token_base *>::iterator it = tree.root(); it.usable(); it = it.right()) {
				if (!it.right().usable()) {
					tree.emplace_root_left(it, signals.at(i));
					break;
				}
				if (get_signal_level(it.data()) == get_signal_level(signals.at(i))) {
					if (is_left_associative(it.data()))
						tree.emplace_right_left(it, signals.at(i));
					else
						tree.emplace_root_left(it, signals.at(i));
					break;
				}
				if (get_signal_level(it.data()) > get_signal_level(signals.at(i))) {
					tree.emplace_root_left(it, signals.at(i));
					break;
				}
			}
		}
		for (typename tree_type<token_base *>::iterator it = tree.root(); it.usable(); it = it.right()) {
			if (!it.right().usable()) {
				tree.emplace_right_right(it, objects.back());
				break;
			}
		}
	}

	void compiler_type::gen_tree(tree_type<token_base *> &tree, std::deque<token_base *> &raw)
	{
		tree.clear();
		if (raw.size() == 1) {
			token_base *obj = raw.front();
			if (obj != nullptr && obj->get_type() == token_types::sblist) {
				auto *sbl = static_cast<token_sblist *>(obj);
				std::deque<token_base *> tokens;
				for (auto &list:sbl->get_list()) {
					for (auto &it:list)
						tokens.push_back(it);
					tokens.push_back(new token_signal(signal_types::com_));
				}
				tokens.pop_back();
				tree_type<token_base *> t;
				gen_tree(t, tokens);
				obj = new token_expr(t);
			}
			tree.emplace_root_left(tree.root(), obj);
		}
		else {
			std::deque<token_base *> signals, objects;
			split_token(raw, signals, objects);
			build_tree(tree, signals, objects);
		}
		optimize_expression(tree);
	}

	void compiler_type::kill_expr(std::deque<token_base *> &tokens)
	{
		std::deque<token_base *> oldt, expr;
		std::swap(tokens, oldt);
		tokens.clear();
		for (auto &ptr:oldt) {
			if (ptr->get_type() == token_types::action || ptr->get_type() == token_types::endline) {
				if (!expr.empty()) {
					tree_type<token_base *> tree;
					gen_tree(tree, expr);
					tokens.push_back(new token_expr(tree));
					expr.clear();
				}
				tokens.push_back(ptr);
			}
			else
				expr.push_back(ptr);
		}
	}
}
<|endoftext|>


<commit_before>#pragma once

#include <hydra/ext/api.hpp>

#include <hydra/world/world.hpp>
#include <hydra/renderer/renderer.hpp>

#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/transform2.hpp>
#include <glm/gtx/quaternion.hpp>

#include <hydra/component/transformcomponent.hpp>

#include <SDL2/SDL.h>

using namespace Hydra::World;

namespace Hydra::Component {
	struct HYDRA_GRAPHICS_API LightComponent final : public IComponent<LightComponent, ComponentBits::Light> {
		glm::vec3 color = glm::vec3(0, 0, 0);

		float zNear = -28.0f;
		float zFar = 28.0f;
		float xNear = -28.0f;
		float xFar = 28.0f;
		float yNear = -28.0f;
		float yFar = 28.0f;
		~LightComponent() final;

		void serialize(nlohmann::json& json) const;
		void deserialize(nlohmann::json& json);
		void registerUI() final;

		const std::string type() const final { return "LightComponent"; }

		inline glm::mat4 getProjectionMatrix() const { return glm::ortho(xNear, xFar, yNear, yFar, zNear, zFar); }
		//inline glm::mat4 getProjectionMatrix() const { return glm::perspective<float>(fov, 1.0f, zNear, zFar); }
		//inline glm::mat4 getViewMatrix() { return glm::translate(glm::mat4_cast(getTransformComponent()->rotation), -getTransformComponent()->position); }
		inline glm::mat4 getViewMatrix() { return glm::lookAt(getTransformComponent()->position, getTransformComponent()->position + glm::vec3(0.2, -0.8, 0), getTransformComponent()->rotation * glm::vec3(0, 1, 0)); }
		inline std::shared_ptr<Hydra::Component::TransformComponent> getTransformComponent() {
			if (auto e = Hydra::World::World::getEntity(entityID); e)
				return e->getComponent<Hydra::Component::TransformComponent>();
			else
				return std::shared_ptr<Hydra::Component::TransformComponent>();
		}
		inline glm::vec3 getDirVec(){
			return glm::normalize(getTransformComponent()->position + glm::vec3(0.2, -0.8, 0));
		}
	};
}
<commit_msg>Added shadows again, working almost flawlessly<commit_after>#pragma once

#include <hydra/ext/api.hpp>

#include <hydra/world/world.hpp>
#include <hydra/renderer/renderer.hpp>

#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/transform2.hpp>
#include <glm/gtx/quaternion.hpp>

#include <hydra/component/transformcomponent.hpp>

#include <SDL2/SDL.h>

using namespace Hydra::World;

namespace Hydra::Component {
	struct HYDRA_GRAPHICS_API LightComponent final : public IComponent<LightComponent, ComponentBits::Light> {
		glm::vec3 color = glm::vec3(0, 0, 0);

		float zNear = -28.0f;
		float zFar = 28.0f;
		float xNear = -28.0f;
		float xFar = 28.0f;
		float yNear = -28.0f;
		float yFar = 28.0f;
		~LightComponent() final;

		void serialize(nlohmann::json& json) const;
		void deserialize(nlohmann::json& json);
		void registerUI() final;

		const std::string type() const final { return "LightComponent"; }

		inline glm::mat4 getProjectionMatrix() const { return glm::ortho(xNear, xFar, yNear, yFar, zNear, zFar); }
		//inline glm::mat4 getProjectionMatrix() const { return glm::perspective<float>(fov, 1.0f, zNear, zFar); }
		//inline glm::mat4 getViewMatrix() { return glm::translate(glm::mat4_cast(getTransformComponent()->rotation), -getTransformComponent()->position); }
		inline glm::mat4 getViewMatrix() { return glm::lookAt(getTransformComponent()->position, getTransformComponent()->position + glm::vec3(0.05, -0.95, 0), getTransformComponent()->rotation * glm::vec3(0, 1, 0)); }
		inline std::shared_ptr<Hydra::Component::TransformComponent> getTransformComponent() {
			if (auto e = Hydra::World::World::getEntity(entityID); e)
				return e->getComponent<Hydra::Component::TransformComponent>();
			else
				return std::shared_ptr<Hydra::Component::TransformComponent>();
		}
		inline glm::vec3 getDirVec(){
			return glm::normalize(getTransformComponent()->position + glm::vec3(0.05, -0.95, 0));
		}
	};
}
<|endoftext|>


<commit_before>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <tools/ReaderPcap.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <fmt/format.h>

// GCOVR_EXCL_START

// Protocol identifiers
const int ETHERTYPE_ARP = 0x0806;
const int ETHERTYPE_IPV4 = 0x0800;
const int IPPROTO_UDP = 17;
// Header and data location specifications
const int ETHERTYPE_OFFSET = 12;
const int ETHERNET_HEADER_SIZE = 14;
#define IP_HEADR_OFFSET      14
#define IP_HEADER_SIZE       20
#define UDP_HEADER_OFFSET    34
#define UDP_HEADER_SIZE       8
#define UDP_DATA_OFFSET      42

ReaderPcap::ReaderPcap(std::string filename)
  : FileName(filename) {
  memset(&Stats, 0, sizeof(struct stats_t));
}

ReaderPcap::~ReaderPcap() {
  if (PcapHandle != NULL ) {
    pcap_close(PcapHandle);
  }
}

int ReaderPcap::open() {
  char errbuff[PCAP_ERRBUF_SIZE];
  PcapHandle = pcap_open_offline(FileName.c_str(), errbuff);
  if (PcapHandle == NULL) {
    return -1;
  }
  return 0;
}

int ReaderPcap::validatePacket(pcap_pkthdr *header, const unsigned char *data) {
  Stats.PacketsTotal++; /**< total packets in pcap file */
  Stats.BytesTotal += header->len;

  if (header->len != header->caplen) {
    Stats.PacketsTruncated++;
    return 0;
  }

  uint16_t type = ntohs(*(uint16_t *)&data[ETHERTYPE_OFFSET]);
  // printf("packet header len %d, type %x\n", header->len, type);

  if (type == ETHERTYPE_ARP) {
    Stats.EtherTypeArp++;
  } else if (type == ETHERTYPE_IPV4) {
    Stats.EtherTypeIpv4++;
  } else {
    Stats.EtherTypeUnknown++;
  }

  if (type != ETHERTYPE_IPV4) { // must be ipv4
    return 0;
  }

  ip *ip = (ip *)&data[IP_HEADR_OFFSET];

  // IPv4 header length must be 20, ip version 4, ipproto must be UDP
  if ((ip->ip_hl != 5) or (ip->ip_v != 4) or (ip->ip_p != IPPROTO_UDP)) {
    Stats.IpProtoUnknown++;
    return 0;
  }
  Stats.IpProtoUDP++;

  assert(header->len > ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE);
  assert(Stats.PacketsTotal == Stats.EtherTypeIpv4 + Stats.EtherTypeArp + Stats.EtherTypeUnknown);
  assert(Stats.EtherTypeIpv4 == Stats.IpProtoUDP + Stats.IpProtoUnknown);

  udphdr *udp = (udphdr *)&data[UDP_HEADER_OFFSET];
  #ifndef __FAVOR_BSD // Why is __FAVOR_BSD not defined here?
  uint16_t UdpLen = htons(udp->len);
  #else
  uint16_t UdpLen = htons(udp->uh_ulen);
  #endif
  assert(UdpLen >= UDP_HEADER_SIZE);

  #if 0
  printf("UDP Payload, Packet %" PRIu64 ", time: %d:%d seconds, size: %d bytes\n",
       Stats.PacketsTotal, (int)header->ts.tv_sec, (int)header->ts.tv_usec,
       (int)header->len);
  printf("ip src->dest: 0x%08x:%d ->0x%08x:%d\n",
         ntohl(*(uint32_t*)&ip->ip_src), ntohs(udp->uh_sport),
         ntohl(*(uint32_t*)&ip->ip_dst), ntohs(udp->uh_dport));
  #endif

  return UdpLen;
}

int ReaderPcap::read(char *buffer, size_t bufferlen) {
  if (PcapHandle == nullptr) {
    return -1;
  }

  struct pcap_pkthdr *Header;
  const unsigned char *Data;
  int ret = pcap_next_ex(PcapHandle, &Header, &Data);
  if (ret < 0) {
    return -1;
  }

  int UdpDataLength;
  if ((UdpDataLength = validatePacket(Header, Data)) <= 0) {
    return UdpDataLength;
  }

  auto DataLength = std::min((size_t)(UdpDataLength - UDP_HEADER_SIZE), bufferlen);
  std::memcpy(buffer, &Data[UDP_DATA_OFFSET], DataLength);

  return DataLength;
}

int ReaderPcap::getStats() {
  if (PcapHandle == NULL) {
    return -1;
  }

  while (true) {
    int RetVal;
    struct pcap_pkthdr *Header;
    const unsigned char *Data;
    if ((RetVal = pcap_next_ex(PcapHandle, &Header, &Data))  < 0) {
      break;
    }
    validatePacket(Header, Data);
  }
  return 0;
}

void ReaderPcap::printPacket(unsigned char *data, size_t len) {
  for (unsigned int i = 0; i < len; i++) {
    if ((i % 16) == 0 && i != 0) {
      printf("\n");
    }
    printf("%.2x ", data[i]);
  }
  printf("\n");
}

void ReaderPcap::printStats() {
  printf("Total packets        %" PRIu64 "\n", Stats.PacketsTotal);
  printf("Truncated packets    %" PRIu64 "\n", Stats.PacketsTruncated);
  printf("Ethertype IPv4       %" PRIu64 "\n", Stats.EtherTypeIpv4);
  printf("  ipproto UDP        %" PRIu64 "\n", Stats.IpProtoUDP);
  printf("  ipproto other      %" PRIu64 "\n", Stats.IpProtoUnknown);
  printf("Ethertype unknown    %" PRIu64 "\n", Stats.EtherTypeUnknown);
  printf("Ethertype ARP        %" PRIu64 "\n", Stats.EtherTypeArp);
  printf("Total bytes          %" PRIu64 "\n", Stats.BytesTotal);

}
// GCOVR_EXCL_STOP
<commit_msg>Update prototype2/tools/ReaderPcap.cpp<commit_after>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <tools/ReaderPcap.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <fmt/format.h>

// GCOVR_EXCL_START

// Protocol identifiers
const int ETHERTYPE_ARP = 0x0806;
const int ETHERTYPE_IPV4 = 0x0800;
const int IPPROTO_UDP = 17;
// Header and data location specifications
const int ETHERTYPE_OFFSET = 12;
const int ETHERNET_HEADER_SIZE = 14;
#define IP_HEADR_OFFSET      14
#define IP_HEADER_SIZE       20
#define UDP_HEADER_OFFSET    34
#define UDP_HEADER_SIZE       8
#define UDP_DATA_OFFSET      42

ReaderPcap::ReaderPcap(std::string filename)
  : FileName(filename) {
  memset(&Stats, 0, sizeof(struct stats_t));
}

ReaderPcap::~ReaderPcap() {
  if (PcapHandle != NULL ) {
    pcap_close(PcapHandle);
  }
}

int ReaderPcap::open() {
  char errbuff[PCAP_ERRBUF_SIZE];
  PcapHandle = pcap_open_offline(FileName.c_str(), errbuff);
  if (PcapHandle == NULL) {
    return -1;
  }
  return 0;
}

int ReaderPcap::validatePacket(pcap_pkthdr *header, const unsigned char *data) {
  Stats.PacketsTotal++; /**< total packets in pcap file */
  Stats.BytesTotal += header->len;

  if (header->len != header->caplen) {
    Stats.PacketsTruncated++;
    return 0;
  }

  uint16_t type = ntohs(*(uint16_t *)&data[ETHERTYPE_OFFSET]);
  // printf("packet header len %d, type %x\n", header->len, type);

  if (type == ETHERTYPE_ARP) {
    Stats.EtherTypeArp++;
  } else if (type == ETHERTYPE_IPV4) {
    Stats.EtherTypeIpv4++;
  } else {
    Stats.EtherTypeUnknown++;
  }

  if (type != ETHERTYPE_IPV4) { // must be ipv4
    return 0;
  }

  ip *ip = (ip *)&data[IP_HEADR_OFFSET];

  // IPv4 header length must be 20, ip version 4, ipproto must be UDP
  if ((ip->ip_hl != 5) or (ip->ip_v != 4) or (ip->ip_p != IPPROTO_UDP)) {
    Stats.IpProtoUnknown++;
    return 0;
  }
  Stats.IpProtoUDP++;

  assert(header->len > ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE);
  assert(Stats.PacketsTotal == Stats.EtherTypeIpv4 + Stats.EtherTypeArp + Stats.EtherTypeUnknown);
  assert(Stats.EtherTypeIpv4 == Stats.IpProtoUDP + Stats.IpProtoUnknown);

  udphdr *udp = (udphdr *)&data[UDP_HEADER_OFFSET];
  #ifndef __FAVOR_BSD // Why is __FAVOR_BSD not defined here?
  uint16_t UdpLen = htons(udp->len);
  #else
  uint16_t UdpLen = htons(udp->uh_ulen);
  #endif
  assert(UdpLen >= UDP_HEADER_SIZE);

  #if 0
  printf("UDP Payload, Packet %" PRIu64 ", time: %d:%d seconds, size: %d bytes\n",
       Stats.PacketsTotal, (int)header->ts.tv_sec, (int)header->ts.tv_usec,
       (int)header->len);
  printf("ip src->dest: 0x%08x:%d ->0x%08x:%d\n",
         ntohl(*(uint32_t*)&ip->ip_src), ntohs(udp->uh_sport),
         ntohl(*(uint32_t*)&ip->ip_dst), ntohs(udp->uh_dport));
  #endif

  return UdpLen;
}

int ReaderPcap::read(char *buffer, size_t bufferlen) {
  if (PcapHandle == nullptr) {
    return -1;
  }

  pcap_pkthdr *Header;
  const unsigned char *Data;
  int ret = pcap_next_ex(PcapHandle, &Header, &Data);
  if (ret < 0) {
    return -1;
  }

  int UdpDataLength;
  if ((UdpDataLength = validatePacket(Header, Data)) <= 0) {
    return UdpDataLength;
  }

  auto DataLength = std::min((size_t)(UdpDataLength - UDP_HEADER_SIZE), bufferlen);
  std::memcpy(buffer, &Data[UDP_DATA_OFFSET], DataLength);

  return DataLength;
}

int ReaderPcap::getStats() {
  if (PcapHandle == NULL) {
    return -1;
  }

  while (true) {
    int RetVal;
    struct pcap_pkthdr *Header;
    const unsigned char *Data;
    if ((RetVal = pcap_next_ex(PcapHandle, &Header, &Data))  < 0) {
      break;
    }
    validatePacket(Header, Data);
  }
  return 0;
}

void ReaderPcap::printPacket(unsigned char *data, size_t len) {
  for (unsigned int i = 0; i < len; i++) {
    if ((i % 16) == 0 && i != 0) {
      printf("\n");
    }
    printf("%.2x ", data[i]);
  }
  printf("\n");
}

void ReaderPcap::printStats() {
  printf("Total packets        %" PRIu64 "\n", Stats.PacketsTotal);
  printf("Truncated packets    %" PRIu64 "\n", Stats.PacketsTruncated);
  printf("Ethertype IPv4       %" PRIu64 "\n", Stats.EtherTypeIpv4);
  printf("  ipproto UDP        %" PRIu64 "\n", Stats.IpProtoUDP);
  printf("  ipproto other      %" PRIu64 "\n", Stats.IpProtoUnknown);
  printf("Ethertype unknown    %" PRIu64 "\n", Stats.EtherTypeUnknown);
  printf("Ethertype ARP        %" PRIu64 "\n", Stats.EtherTypeArp);
  printf("Total bytes          %" PRIu64 "\n", Stats.BytesTotal);

}
// GCOVR_EXCL_STOP
<|endoftext|>


<commit_before>/* -*- mode: c++; c-basic-offset:4 -*-
    utils/validation.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2008 Klarälvdalens Datakonsult AB

    Kleopatra 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.

    Kleopatra 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 this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "validation.h"

#include <utils/multivalidator.h>

#include <KDebug>

#include <QRegExp>
#include <QUrl>

#include <cassert>

using namespace Kleo;

static const char email_rx[] = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
// these are modeled after gnupg/g10/keygen.c:ask_user_id:
static const char name_rx[] = "[^0-9<>][^<>@]{4,}";
static const char comment_rx[] = "[^()]*";

namespace {

    class EMailValidator : public QRegExpValidator {
    public:
        explicit EMailValidator( QObject * parent=0 ) : QRegExpValidator( QRegExp( email_rx ), parent ) {}

        /* reimp */ void fixup( QString & ) const {}

        /* reimp */ State validate( QString & str, int & pos ) const {
            const int atIdx = str.lastIndexOf( '@' );
            if ( atIdx < 0 || str.endsWith( '@' ) )
                return QRegExpValidator::validate( str, pos );

            // toAce/fromAce doesn't like intermediate domain names,
            // so we fix them up with something innocuous to help it
            // along, and which we strip again afterwards

            QString domain = str.mid( atIdx + 1 ).toLower();
            const int dotIndex = domain.lastIndexOf( '.' );
            const bool needsOrgAdded = domain.endsWith( '.' );
            const bool needsDotOrgAdded = !needsOrgAdded && ( dotIndex < 0 || dotIndex == domain.size() - 2 ) ; // yeah, foo.s also disrupts fromAce...
            if ( needsOrgAdded )
                domain += "org";
            if ( needsDotOrgAdded )
                domain += ".org";
            const QByteArray domainEncoded = QUrl::toAce( domain );
            const QString domainRestored = QUrl::fromAce( domainEncoded );
            QString encoded = str.left( atIdx ) + '@' + QString::fromLatin1( domainEncoded );
            if ( needsDotOrgAdded ) {
                assert( encoded.endsWith( ".org" ) );
                encoded.chop( 4 );
            }
            if ( needsOrgAdded ) {
                assert( encoded.endsWith( ".org" ) );
                encoded.chop( 3 ); // '.' was part of domain before
            }
            kDebug() << "\n str           :" << str
                     << "\n domain        :" << domain
                     << "\n domainEncoded :" << domainEncoded
                     << "\n domainRestored:" << domainRestored
                     << "\n encoded       :" << encoded ;
            if ( domain != domainRestored )
                return Invalid;
            int dummyPosition = 0;
            return QRegExpValidator::validate( encoded, dummyPosition );
        }

    };

}

QValidator * Validation::email( QObject * parent ) {
    return new EMailValidator( parent );
}

QValidator * Validation::email( const QRegExp & addRX, QObject * parent ) {
    return new MultiValidator( email(), new QRegExpValidator( addRX, 0 ), parent );
}

QValidator * Validation::pgpName( QObject * parent ) {
    return new QRegExpValidator( QRegExp( name_rx ), parent );
}

QValidator * Validation::pgpName( const QRegExp & addRX, QObject * parent ) {
    return new MultiValidator( pgpName(), new QRegExpValidator( addRX, 0 ), parent );
}

QValidator * Validation::pgpComment( QObject * parent ) {
    return new QRegExpValidator( QRegExp( comment_rx ), parent );
}

QValidator * Validation::pgpComment( const QRegExp & addRX, QObject * parent ) {
    return new MultiValidator( pgpComment(), new QRegExpValidator( addRX, 0 ), parent );
}

<commit_msg>EMailValidator: oops, allow capital letters, too.<commit_after>/* -*- mode: c++; c-basic-offset:4 -*-
    utils/validation.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2008 Klarälvdalens Datakonsult AB

    Kleopatra 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.

    Kleopatra 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 this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "validation.h"

#include <utils/multivalidator.h>

#include <KDebug>

#include <QRegExp>
#include <QUrl>

#include <cassert>

using namespace Kleo;

static const char email_rx[] = "[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?";
// these are modeled after gnupg/g10/keygen.c:ask_user_id:
static const char name_rx[] = "[^0-9<>][^<>@]{4,}";
static const char comment_rx[] = "[^()]*";

namespace {

    class EMailValidator : public QRegExpValidator {
    public:
        explicit EMailValidator( QObject * parent=0 ) : QRegExpValidator( QRegExp( email_rx ), parent ) {}

        /* reimp */ void fixup( QString & ) const {}

        /* reimp */ State validate( QString & str, int & pos ) const {
            const int atIdx = str.lastIndexOf( '@' );
            if ( atIdx < 0 || str.endsWith( '@' ) )
                return QRegExpValidator::validate( str, pos );

            // toAce/fromAce doesn't like intermediate domain names,
            // so we fix them up with something innocuous to help it
            // along, and which we strip again afterwards

            QString domain = str.mid( atIdx + 1 ).toLower();
            const int dotIndex = domain.lastIndexOf( '.' );
            const bool needsOrgAdded = domain.endsWith( '.' );
            const bool needsDotOrgAdded = !needsOrgAdded && ( dotIndex < 0 || dotIndex == domain.size() - 2 ) ; // yeah, foo.s also disrupts fromAce...
            if ( needsOrgAdded )
                domain += "org";
            if ( needsDotOrgAdded )
                domain += ".org";
            const QByteArray domainEncoded = QUrl::toAce( domain );
            const QString domainRestored = QUrl::fromAce( domainEncoded );
            QString encoded = str.left( atIdx ) + '@' + QString::fromLatin1( domainEncoded );
            if ( needsDotOrgAdded ) {
                assert( encoded.endsWith( ".org" ) );
                encoded.chop( 4 );
            }
            if ( needsOrgAdded ) {
                assert( encoded.endsWith( ".org" ) );
                encoded.chop( 3 ); // '.' was part of domain before
            }
            kDebug() << "\n str           :" << str
                     << "\n domain        :" << domain
                     << "\n domainEncoded :" << domainEncoded
                     << "\n domainRestored:" << domainRestored
                     << "\n encoded       :" << encoded ;
            if ( domain != domainRestored )
                return Invalid;
            int dummyPosition = 0;
            return QRegExpValidator::validate( encoded, dummyPosition );
        }

    };

}

QValidator * Validation::email( QObject * parent ) {
    return new EMailValidator( parent );
}

QValidator * Validation::email( const QRegExp & addRX, QObject * parent ) {
    return new MultiValidator( email(), new QRegExpValidator( addRX, 0 ), parent );
}

QValidator * Validation::pgpName( QObject * parent ) {
    return new QRegExpValidator( QRegExp( name_rx ), parent );
}

QValidator * Validation::pgpName( const QRegExp & addRX, QObject * parent ) {
    return new MultiValidator( pgpName(), new QRegExpValidator( addRX, 0 ), parent );
}

QValidator * Validation::pgpComment( QObject * parent ) {
    return new QRegExpValidator( QRegExp( comment_rx ), parent );
}

QValidator * Validation::pgpComment( const QRegExp & addRX, QObject * parent ) {
    return new MultiValidator( pgpComment(), new QRegExpValidator( addRX, 0 ), parent );
}

<|endoftext|>


<commit_before>#include "Capture.h"
#include "Compute.h"
#include "ImageLogger.h"
#include "Timer.h"

#include "Motor.h"
#include "Radio.h"
#include "Navio/Util.h"

#include <iostream>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>

static volatile bool quit = false;

static void Quit(int) {
    quit = true;
}

static const int refreshRate = 30;

int main(int /*argc*/, char** /*argv*/) {
    if (! check_apm()) {
        system("sudo modprobe bcm2835-v4l2");

        Capture cap(0);
        ImageLogger log;
        Compute compute(&cap, &log);
        cap.Start();
        log.Start();
        compute.Start();

        Motor motor;
        Radio rc;
        Timer timer;
        float steer = 0;

        signal(SIGHUP, Quit);
        signal(SIGINT, Quit);

        timer.Start();
        while (! quit) {
            OutputData data;
            compute.SwapOutputData(data);

            float throttle = rc.ReadThrottle();
            float leftMotor, rightMotor;
            if (data.direction == GoBack) {
                if (steer > 0.) {
                    leftMotor  = -throttle;
                    rightMotor =  throttle;
                } else {
                    rightMotor = -throttle;
                    leftMotor  =  throttle;
                }
            } else {
                if (data.direction == GoStraight) {
                    leftMotor  = throttle;
                    rightMotor = throttle;
                } else {
                    steer = 18. * (M_PI_2 - atan2(data.hiY - data.loY, data.hiX - data.loX));
                    //std::cerr << "steer = " << steer << std::endl;
                    leftMotor  = steer > 0. ? (1. - std::min( 1.F,steer)) * throttle : throttle;
                    rightMotor = steer < 0. ? (1. + std::max(-1.F,steer)) * throttle : throttle;
                }
            }
            motor.SetLeftMotor (leftMotor);
            motor.SetRightMotor(rightMotor);

            struct timespec sleep = {0, 1000 * timer.NextSleep(refreshRate, INT_MAX)};
            nanosleep(&sleep, NULL);
        }

        motor.SetLeftMotor (0.);
        motor.SetRightMotor(0.);

        cap.Stop();
        compute.Stop();
        log.Stop();
    }
    return 0;
}
<commit_msg>throttle tweaks<commit_after>#include "Capture.h"
#include "Compute.h"
#include "ImageLogger.h"
#include "Timer.h"

#include "Motor.h"
#include "Radio.h"
#include "Navio/Util.h"

#include <iostream>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>

static volatile bool quit = false;

static void Quit(int) {
    quit = true;
}

static const int refreshRate = 30;

int main(int /*argc*/, char** /*argv*/) {
    if (! check_apm()) {
        system("sudo modprobe bcm2835-v4l2");

        Capture cap(0);
        ImageLogger log;
        Compute compute(&cap, &log);
        cap.Start();
        log.Start();
        compute.Start();

        Motor motor;
        Radio rc;
        Timer timer;
        float steer = 0;

        signal(SIGHUP, Quit);
        signal(SIGINT, Quit);

        timer.Start();
        while (! quit) {
            OutputData data;
            compute.SwapOutputData(data);

            float throttle = rc.ReadThrottle();
            float leftMotor, rightMotor;
            if (data.direction == GoBack) {
                throttle = std::min(0.75F, throttle);
                if (steer > 0.) {
                    leftMotor  = -throttle;
                    rightMotor =  throttle;
                } else {
                    rightMotor = -throttle;
                    leftMotor  =  throttle;
                }
            } else {
                if (data.direction == GoStraight) {
                    leftMotor  = throttle;
                    rightMotor = throttle;
                } else {
                    steer = (20. - 5.*throttle) * (M_PI_2 - atan2(data.hiY - data.loY, data.hiX - data.loX));
                    //std::cerr << "steer = " << steer << std::endl;
                    leftMotor  = steer > 0. ? (1. - std::min( 1.F,steer)) * throttle : throttle;
                    rightMotor = steer < 0. ? (1. + std::max(-1.F,steer)) * throttle : throttle;
                }
            }
            motor.SetLeftMotor (leftMotor);
            motor.SetRightMotor(rightMotor);

            struct timespec sleep = {0, 1000 * timer.NextSleep(refreshRate, INT_MAX)};
            nanosleep(&sleep, NULL);
        }

        motor.SetLeftMotor (0.);
        motor.SetRightMotor(0.);

        cap.Stop();
        compute.Stop();
        log.Stop();
    }
    return 0;
}
<|endoftext|>


<commit_before>
#include "numerics/cbrt.hpp"

#include <pmmintrin.h>

#include <cstdint>
#include <limits>

namespace principia {
namespace numerics {

constexpr std::uint64_t C = 0x2A9F7893782DA1CE;
static const __m128d sign_bit =
    _mm_castsi128_pd(_mm_cvtsi64_si128(0x8000'0000'0000'0000));
static const __m128d sign_exponent_and_sixteen_bits_of_mantissa =
    _mm_castsi128_pd(_mm_cvtsi64_si128(0xFFFF'FFF0'0000'0000));
// No overflow or underflow occurs in intermediate computations for
// y ∈ [y₁, y₂].
// NOTE(egg): the σs do not rescale enough to put the least normal or greatest
// finite magnitudes inside the non-rescaling range; for very small and very
// large values, rescaling occurs twice.
constexpr double y₁ = 0x1p-225;
constexpr double σ₁ = 0x1p-154;
constexpr double σ₁⁻³ = 1 / (σ₁ * σ₁ * σ₁);
constexpr double y₂ = 0x1p237;
constexpr double σ₂ = 0x1p154;
constexpr double σ₂⁻³ = 1 / (σ₂ * σ₂ * σ₂);
static_assert(σ₁⁻³ * y₁ == y₂, "Incorrect σ₁");
static_assert(σ₂⁻³ * y₂ == y₁, "Incorrect σ₂");
double cbrt(double const y) {
  __m128d const y_0 = _mm_set_sd(y);
  __m128d const sign = _mm_and_pd(sign_bit, y_0);
  __m128d const abs_y_0 = _mm_andnot_pd(sign_bit, y_0);
  double const abs_y = _mm_cvtsd_f64(abs_y_0);
  // TODO(egg): we take the absolute value two or three times when going through
  // the rescaling paths; consider having a cbrt_positive function, or a
  // cbrt_positive_unscaled function and four rescaling paths.
  if (abs_y < y₁) {
    if (abs_y == 0) {
      return y;
    }
    return cbrt(y * σ₁⁻³) * σ₁;
  } else if (abs_y > y₂) {
    if (abs_y == std::numeric_limits<double>::infinity()) {
      return y;
    }
    return cbrt(y * σ₂⁻³) * σ₂;
  }
  // Approximate ∛y with an error below 3,2 %.  The value of C is chosen to
  // minimize the maximal error of ξ as an approximation of ∛y, ignoring
  // rounding.
  std::uint64_t const Y = _mm_cvtsi128_si64(_mm_castpd_si128(abs_y_0));
  std::uint64_t const Q = C + Y / 3;
  double const q = _mm_cvtsd_f64(_mm_castsi128_pd(_mm_cvtsi64_si128(Q)));
  double const q³ = q * q * q;
  // An approximation of ∛y with a relative error below 2⁻¹⁵.
  double const ξ = q - (q³ - abs_y) * q / (2 * q³ + abs_y);
  double const x = _mm_cvtsd_f64(
      _mm_and_pd(_mm_set_sd(ξ), sign_exponent_and_sixteen_bits_of_mantissa));
  // One round of 6th order Householder.
  double const x³ = x * x * x;
  double const x⁶ = x³ * x³;
  double const y² = y * y;
  double const x_sign_y = _mm_cvtsd_f64(_mm_or_pd(_mm_set_sd(x)), sign);
  double const numerator =
      x_sign_y * (x³ - abs_y) * ((5 * x³ + 17 * abs_y) * x³ + 5 * y²);
  double const denominator =
      (7 * x³ + 42 * abs_y) * x⁶ + (30 * x³ + 2 * abs_y) * y²;
  return x_sign_y - numerator / denominator;
}

}  // namespace numerics
}  // namespace principia
<commit_msg>misplaced parenthesis<commit_after>
#include "numerics/cbrt.hpp"

#include <pmmintrin.h>

#include <cstdint>
#include <limits>

namespace principia {
namespace numerics {

constexpr std::uint64_t C = 0x2A9F7893782DA1CE;
static const __m128d sign_bit =
    _mm_castsi128_pd(_mm_cvtsi64_si128(0x8000'0000'0000'0000));
static const __m128d sign_exponent_and_sixteen_bits_of_mantissa =
    _mm_castsi128_pd(_mm_cvtsi64_si128(0xFFFF'FFF0'0000'0000));
// No overflow or underflow occurs in intermediate computations for
// y ∈ [y₁, y₂].
// NOTE(egg): the σs do not rescale enough to put the least normal or greatest
// finite magnitudes inside the non-rescaling range; for very small and very
// large values, rescaling occurs twice.
constexpr double y₁ = 0x1p-225;
constexpr double σ₁ = 0x1p-154;
constexpr double σ₁⁻³ = 1 / (σ₁ * σ₁ * σ₁);
constexpr double y₂ = 0x1p237;
constexpr double σ₂ = 0x1p154;
constexpr double σ₂⁻³ = 1 / (σ₂ * σ₂ * σ₂);
static_assert(σ₁⁻³ * y₁ == y₂, "Incorrect σ₁");
static_assert(σ₂⁻³ * y₂ == y₁, "Incorrect σ₂");
double cbrt(double const y) {
  __m128d const y_0 = _mm_set_sd(y);
  __m128d const sign = _mm_and_pd(sign_bit, y_0);
  __m128d const abs_y_0 = _mm_andnot_pd(sign_bit, y_0);
  double const abs_y = _mm_cvtsd_f64(abs_y_0);
  // TODO(egg): we take the absolute value two or three times when going through
  // the rescaling paths; consider having a cbrt_positive function, or a
  // cbrt_positive_unscaled function and four rescaling paths.
  if (abs_y < y₁) {
    if (abs_y == 0) {
      return y;
    }
    return cbrt(y * σ₁⁻³) * σ₁;
  } else if (abs_y > y₂) {
    if (abs_y == std::numeric_limits<double>::infinity()) {
      return y;
    }
    return cbrt(y * σ₂⁻³) * σ₂;
  }
  // Approximate ∛y with an error below 3,2 %.  The value of C is chosen to
  // minimize the maximal error of ξ as an approximation of ∛y, ignoring
  // rounding.
  std::uint64_t const Y = _mm_cvtsi128_si64(_mm_castpd_si128(abs_y_0));
  std::uint64_t const Q = C + Y / 3;
  double const q = _mm_cvtsd_f64(_mm_castsi128_pd(_mm_cvtsi64_si128(Q)));
  double const q³ = q * q * q;
  // An approximation of ∛y with a relative error below 2⁻¹⁵.
  double const ξ = q - (q³ - abs_y) * q / (2 * q³ + abs_y);
  double const x = _mm_cvtsd_f64(
      _mm_and_pd(_mm_set_sd(ξ), sign_exponent_and_sixteen_bits_of_mantissa));
  // One round of 6th order Householder.
  double const x³ = x * x * x;
  double const x⁶ = x³ * x³;
  double const y² = y * y;
  double const x_sign_y = _mm_cvtsd_f64(_mm_or_pd(_mm_set_sd(x), sign));
  double const numerator =
      x_sign_y * (x³ - abs_y) * ((5 * x³ + 17 * abs_y) * x³ + 5 * y²);
  double const denominator =
      (7 * x³ + 42 * abs_y) * x⁶ + (30 * x³ + 2 * abs_y) * y²;
  return x_sign_y - numerator / denominator;
}

}  // namespace numerics
}  // namespace principia
<|endoftext|>