<commit_before>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

#include <stdarg.h>

#include "LuaEnvironment.h"
#include "Assert.h"
#include "StringUtils.h"
#include "LuaStack.h"
#include "Device.h"
#include "LuaResource.h"
#include "ResourceManager.h"

namespace crown
{

extern int vector3_add(lua_State* L);
extern int vector3_subtract(lua_State* L);
extern int vector3_multiply(lua_State* L);
extern int vector3_divide(lua_State* L);
extern int vector3_negate(lua_State* L);
extern int vector2(lua_State* L);
extern int vector3(lua_State* L);
extern int matrix4x4(lua_State* L);
extern int quaternion(lua_State* L);

//-----------------------------------------------------------------------------
CE_EXPORT int luaopen_libcrown(lua_State* /*L*/)
{
	LuaEnvironment* env = device()->lua_environment();

	load_int_setting(*env);
	load_float_setting(*env);
	load_string_setting(*env);

	load_vector2(*env);
	load_vector3(*env);
	load_matrix4x4(*env);
	load_quaternion(*env);
	load_math(*env);
	load_window(*env);
	load_mouse(*env);
	load_keyboard(*env);
	load_accelerometer(*env);
	load_device(*env);
	load_resource_package(*env);

	load_unit(*env);
	load_camera(*env);
	load_world(*env);
	load_mesh(*env);
	load_sprite(*env);

	return 1;
}

//-----------------------------------------------------------------------------
static int crown_lua_vector2_call(lua_State* L)
{
	lua_remove(L, 1);
	return vector2(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_vector3_call(lua_State* L)
{
	lua_remove(L, 1);
	return vector3(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_matrix4x4_call(lua_State* L)
{
	lua_remove(L, 1);
	return matrix4x4(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_quaternion_call(lua_State* L)
{
	lua_remove(L, 1);
	return quaternion(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_add(lua_State* L)
{
	return vector3_add(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_sub(lua_State* L)
{
	return vector3_subtract(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_mul(lua_State* L)
{
	return vector3_multiply(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_div(lua_State* L)
{
	return vector3_divide(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_unm(lua_State* L)
{
	return vector3_negate(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_require(lua_State* L)
{
	LuaStack stack(L);

	const char* filename = stack.get_string(1);

	const ResourceId lua_res = device()->resource_manager()->load("lua", filename);
	device()->resource_manager()->flush();

	const LuaResource* lr = (LuaResource*) device()->resource_manager()->data(lua_res);
	luaL_loadbuffer(L, (const char*) lr->code(), lr->size(), "");

	device()->resource_manager()->unload(lua_res);

	return 1;
}

//-----------------------------------------------------------------------------
LuaEnvironment::LuaEnvironment()
	: m_state(luaL_newstate())
{
}

//-----------------------------------------------------------------------------
void LuaEnvironment::init()
{
	// Open default libraries
	luaL_openlibs(m_state);
	// Open Crown library
	lua_cpcall(m_state, luaopen_libcrown, NULL);

	// Register custom loader
	lua_getfield(m_state, LUA_GLOBALSINDEX, "package");
	lua_getfield(m_state, -1, "loaders");
	lua_remove(m_state, -2);

	int num_loaders = 0;
	lua_pushnil(m_state);
	while (lua_next(m_state, -2) != 0)
	{
		lua_pop(m_state, 1);
		num_loaders++;
	}

	lua_pushinteger(m_state, num_loaders + 1);
	lua_pushcfunction(m_state, crown_lua_require);
	lua_rawset(m_state, -3);

	lua_pop(m_state, 1);

	// Create metatable for lightuserdata
	lua_pushlightuserdata(m_state, (void*)0x0);
	luaL_newmetatable(m_state, "Lightuserdata_mt");
	lua_setmetatable(m_state, -2);
	lua_pop(m_state, 1);

	luaL_newmetatable(m_state, "Lightuserdata_mt");

	lua_pushstring(m_state, "__add");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_add);
	lua_settable(m_state, 1);

	lua_pushstring(m_state, "__sub");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_sub);
	lua_settable(m_state, 1);

	lua_pushstring(m_state, "__mul");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_mul);
	lua_settable(m_state, 1);

	lua_pushstring(m_state, "__div");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_div);
	lua_settable(m_state, 1);

	lua_pushstring(m_state, "__unm");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_unm);
	lua_settable(m_state, 1);

	// Vector2 metatable
	luaL_newmetatable(m_state, "Vector2_mt");
	lua_pushvalue(m_state, -1);
	lua_setfield(m_state, -2, "__index");
	lua_pushcfunction(m_state, crown_lua_vector2_call);
	lua_setfield(m_state, -2, "__call");

	lua_getglobal(m_state, "Vector2");
	lua_pushvalue(m_state, -2); // Duplicate metatable
	lua_setmetatable(m_state, -2); // setmetatable(Vector2, Vector2_mt)

	// Vector3 metatable
	luaL_newmetatable(m_state, "Vector3_mt");
	lua_pushvalue(m_state, -1);
	lua_setfield(m_state, -2, "__index");
	lua_pushcfunction(m_state, crown_lua_vector3_call);
	lua_setfield(m_state, -2, "__call");

	lua_getglobal(m_state, "Vector3");
	lua_pushvalue(m_state, -2); // Duplicate metatable
	lua_setmetatable(m_state, -2); // setmetatable(Vector3, Vector3_mt)

	// Matrix4x4 metatable
	luaL_newmetatable(m_state, "Matrix4x4_mt");
	lua_pushvalue(m_state, -1);
	lua_setfield(m_state, -2, "__index");
	lua_pushcfunction(m_state, crown_lua_matrix4x4_call);
	lua_setfield(m_state, -2, "__call");

	lua_getglobal(m_state, "Matrix4x4");
	lua_pushvalue(m_state, -2); // Duplicate metatable
	lua_setmetatable(m_state, -2); // setmetatable(Matrix4x4, Matrix4x4_mt)

	// Quaternion metatable
	luaL_newmetatable(m_state, "Quaternion_mt");
	lua_pushvalue(m_state, -1);
	lua_setfield(m_state, -2, "__index");
	lua_pushcfunction(m_state, crown_lua_quaternion_call);
	lua_setfield(m_state, -2, "__call");

	lua_getglobal(m_state, "Quaternion");
	lua_pushvalue(m_state, -2); // Duplicate metatable
	lua_setmetatable(m_state, -2); // setmetatable(Quaternion, Quaternion_mt)
}

//-----------------------------------------------------------------------------
void LuaEnvironment::shutdown()
{
	lua_close(m_state);
}

//-----------------------------------------------------------------------------
bool LuaEnvironment::load_and_execute(const char* res_name)
{
	CE_ASSERT_NOT_NULL(res_name);

	ResourceManager* resman = device()->resource_manager();

	// Load the resource
	ResourceId res_id = resman->load("lua", res_name);
	resman->flush();
	LuaResource* lr = (LuaResource*) resman->data(res_id);

	lua_getglobal(m_state, "debug");
	lua_getfield(m_state, -1, "traceback");
	if (luaL_loadbuffer(m_state, (const char*) lr->code(), lr->size(), res_name) == 0)
	{
		if (lua_pcall(m_state, 0, 0, -2) == 0)
		{
			// Unloading is OK since the script data has been copied to Lua
			resman->unload(res_id);
			lua_pop(m_state, 2); // Pop debug.traceback
			return true;
		}
	}

	error();
	lua_pop(m_state, 2); // Pop debug.traceback
	return false;
}

//-----------------------------------------------------------------------------
bool LuaEnvironment::execute_string(const char* s)
{
	CE_ASSERT_NOT_NULL(s);

	lua_getglobal(m_state, "debug");
	lua_getfield(m_state, -1, "traceback");
	if (luaL_loadstring(m_state, s) == 0)
	{
		if (lua_pcall(m_state, 0, 0, -2) == 0)
		{
			// Unloading is OK since the script data has been copied to Lua
			lua_pop(m_state, 2); // Pop debug.traceback
			return true;
		}
	}

	error();
	lua_pop(m_state, 2); // Pop debug.traceback
	return false;
}

//-----------------------------------------------------------------------------
void LuaEnvironment::load_module_function(const char* module, const char* name, const lua_CFunction func)
{
	luaL_Reg entry[2];

	entry[0].name = name;
	entry[0].func = func;
	entry[1].name = NULL;
	entry[1].func = NULL;

	luaL_register(m_state, module, entry);
}

//-----------------------------------------------------------
void LuaEnvironment::load_module_enum(const char* /*module*/, const char* name, uint32_t value)
{
	lua_pushinteger(m_state, value);
	lua_setfield(m_state, -2, name);
}

//-----------------------------------------------------------------------------
bool LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
{
	CE_ASSERT_NOT_NULL(func);

	LuaStack stack(m_state);

	va_list vl;
	va_start(vl, argc);

	lua_getglobal(m_state, "debug");
	lua_getfield(m_state, -1, "traceback");
	lua_getglobal(m_state, func);

	for (uint8_t i = 0; i < argc; i++)
	{
		const int type = va_arg(vl, int);
		switch (type)
		{
			case ARGUMENT_FLOAT:
			{
				stack.push_float(va_arg(vl, double));
				break;
			}
			default:
			{
				CE_ASSERT(false, "Oops, lua argument unknown");
				break;
			}
		}
	}

	va_end(vl);

	if (lua_pcall(m_state, argc, 0, -argc - 2) != 0)
	{
		error();
		lua_pop(m_state, 2); // Pop debug.traceback
		return false;
	}

	lua_pop(m_state, 2); // Pop debug.traceback

	return true;
}

//-----------------------------------------------------------------------------
void LuaEnvironment::error()
{
	const char* msg = lua_tostring(m_state, -1);
	Log::e(msg);
	lua_pop(m_state, 1);
}

} // namespace crown<commit_msg>Add +, -, *, / operators to Vector2 too<commit_after>/*
Copyright (c) 2013 Daniele Bartolini, Michele Rossi
Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

#include <stdarg.h>

#include "LuaEnvironment.h"
#include "Assert.h"
#include "StringUtils.h"
#include "LuaStack.h"
#include "Device.h"
#include "LuaResource.h"
#include "ResourceManager.h"

namespace crown
{

extern int vector2_add(lua_State* L);
extern int vector2_subtract(lua_State* L);
extern int vector2_multiply(lua_State* L);
extern int vector2_divide(lua_State* L);
extern int vector2_negate(lua_State* L);
extern int vector3_add(lua_State* L);
extern int vector3_subtract(lua_State* L);
extern int vector3_multiply(lua_State* L);
extern int vector3_divide(lua_State* L);
extern int vector3_negate(lua_State* L);
extern int vector2(lua_State* L);
extern int vector3(lua_State* L);
extern int matrix4x4(lua_State* L);
extern int quaternion(lua_State* L);

//-----------------------------------------------------------------------------
CE_EXPORT int luaopen_libcrown(lua_State* /*L*/)
{
	LuaEnvironment* env = device()->lua_environment();

	load_int_setting(*env);
	load_float_setting(*env);
	load_string_setting(*env);

	load_vector2(*env);
	load_vector3(*env);
	load_matrix4x4(*env);
	load_quaternion(*env);
	load_math(*env);
	load_window(*env);
	load_mouse(*env);
	load_keyboard(*env);
	load_accelerometer(*env);
	load_device(*env);
	load_resource_package(*env);

	load_unit(*env);
	load_camera(*env);
	load_world(*env);
	load_mesh(*env);
	load_sprite(*env);

	return 1;
}

//-----------------------------------------------------------------------------
static int crown_lua_vector2_call(lua_State* L)
{
	lua_remove(L, 1);
	return vector2(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_vector3_call(lua_State* L)
{
	lua_remove(L, 1);
	return vector3(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_matrix4x4_call(lua_State* L)
{
	lua_remove(L, 1);
	return matrix4x4(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_quaternion_call(lua_State* L)
{
	lua_remove(L, 1);
	return quaternion(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_add(lua_State* L)
{
	LuaStack stack(L);

	if (stack.is_vector3(1))
	{
		return vector3_add(L);
	}
	return vector2_add(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_sub(lua_State* L)
{
	LuaStack stack(L);

	if (stack.is_vector3(1))
	{
		return vector3_subtract(L);
	}
	return vector2_subtract(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_mul(lua_State* L)
{
	LuaStack stack(L);

	if (stack.is_vector3(1))
	{
		return vector3_multiply(L);
	}
	return vector2_multiply(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_div(lua_State* L)
{
	LuaStack stack(L);

	if (stack.is_vector3(1))
	{
		return vector3_divide(L);
	}
	return vector2_divide(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_lightuserdata_unm(lua_State* L)
{
	LuaStack stack(L);

	if (stack.is_vector3(1))
	{
		return vector3_negate(L);
	}
	return vector2_negate(L);
}

//-----------------------------------------------------------------------------
static int crown_lua_require(lua_State* L)
{
	LuaStack stack(L);

	const char* filename = stack.get_string(1);

	const ResourceId lua_res = device()->resource_manager()->load("lua", filename);
	device()->resource_manager()->flush();

	const LuaResource* lr = (LuaResource*) device()->resource_manager()->data(lua_res);
	luaL_loadbuffer(L, (const char*) lr->code(), lr->size(), "");

	device()->resource_manager()->unload(lua_res);

	return 1;
}

//-----------------------------------------------------------------------------
LuaEnvironment::LuaEnvironment()
	: m_state(luaL_newstate())
{
}

//-----------------------------------------------------------------------------
void LuaEnvironment::init()
{
	// Open default libraries
	luaL_openlibs(m_state);
	// Open Crown library
	lua_cpcall(m_state, luaopen_libcrown, NULL);

	// Register custom loader
	lua_getfield(m_state, LUA_GLOBALSINDEX, "package");
	lua_getfield(m_state, -1, "loaders");
	lua_remove(m_state, -2);

	int num_loaders = 0;
	lua_pushnil(m_state);
	while (lua_next(m_state, -2) != 0)
	{
		lua_pop(m_state, 1);
		num_loaders++;
	}

	lua_pushinteger(m_state, num_loaders + 1);
	lua_pushcfunction(m_state, crown_lua_require);
	lua_rawset(m_state, -3);

	lua_pop(m_state, 1);

	// Create metatable for lightuserdata
	lua_pushlightuserdata(m_state, (void*)0x0);
	luaL_newmetatable(m_state, "Lightuserdata_mt");
	lua_setmetatable(m_state, -2);
	lua_pop(m_state, 1);

	luaL_newmetatable(m_state, "Lightuserdata_mt");

	lua_pushstring(m_state, "__add");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_add);
	lua_settable(m_state, 1);

	lua_pushstring(m_state, "__sub");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_sub);
	lua_settable(m_state, 1);

	lua_pushstring(m_state, "__mul");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_mul);
	lua_settable(m_state, 1);

	lua_pushstring(m_state, "__div");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_div);
	lua_settable(m_state, 1);

	lua_pushstring(m_state, "__unm");
	lua_pushcfunction(m_state, crown_lua_lightuserdata_unm);
	lua_settable(m_state, 1);

	// Vector2 metatable
	luaL_newmetatable(m_state, "Vector2_mt");
	lua_pushvalue(m_state, -1);
	lua_setfield(m_state, -2, "__index");
	lua_pushcfunction(m_state, crown_lua_vector2_call);
	lua_setfield(m_state, -2, "__call");

	lua_getglobal(m_state, "Vector2");
	lua_pushvalue(m_state, -2); // Duplicate metatable
	lua_setmetatable(m_state, -2); // setmetatable(Vector2, Vector2_mt)

	// Vector3 metatable
	luaL_newmetatable(m_state, "Vector3_mt");
	lua_pushvalue(m_state, -1);
	lua_setfield(m_state, -2, "__index");
	lua_pushcfunction(m_state, crown_lua_vector3_call);
	lua_setfield(m_state, -2, "__call");

	lua_getglobal(m_state, "Vector3");
	lua_pushvalue(m_state, -2); // Duplicate metatable
	lua_setmetatable(m_state, -2); // setmetatable(Vector3, Vector3_mt)

	// Matrix4x4 metatable
	luaL_newmetatable(m_state, "Matrix4x4_mt");
	lua_pushvalue(m_state, -1);
	lua_setfield(m_state, -2, "__index");
	lua_pushcfunction(m_state, crown_lua_matrix4x4_call);
	lua_setfield(m_state, -2, "__call");

	lua_getglobal(m_state, "Matrix4x4");
	lua_pushvalue(m_state, -2); // Duplicate metatable
	lua_setmetatable(m_state, -2); // setmetatable(Matrix4x4, Matrix4x4_mt)

	// Quaternion metatable
	luaL_newmetatable(m_state, "Quaternion_mt");
	lua_pushvalue(m_state, -1);
	lua_setfield(m_state, -2, "__index");
	lua_pushcfunction(m_state, crown_lua_quaternion_call);
	lua_setfield(m_state, -2, "__call");

	lua_getglobal(m_state, "Quaternion");
	lua_pushvalue(m_state, -2); // Duplicate metatable
	lua_setmetatable(m_state, -2); // setmetatable(Quaternion, Quaternion_mt)
}

//-----------------------------------------------------------------------------
void LuaEnvironment::shutdown()
{
	lua_close(m_state);
}

//-----------------------------------------------------------------------------
bool LuaEnvironment::load_and_execute(const char* res_name)
{
	CE_ASSERT_NOT_NULL(res_name);

	ResourceManager* resman = device()->resource_manager();

	// Load the resource
	ResourceId res_id = resman->load("lua", res_name);
	resman->flush();
	LuaResource* lr = (LuaResource*) resman->data(res_id);

	lua_getglobal(m_state, "debug");
	lua_getfield(m_state, -1, "traceback");
	if (luaL_loadbuffer(m_state, (const char*) lr->code(), lr->size(), res_name) == 0)
	{
		if (lua_pcall(m_state, 0, 0, -2) == 0)
		{
			// Unloading is OK since the script data has been copied to Lua
			resman->unload(res_id);
			lua_pop(m_state, 2); // Pop debug.traceback
			return true;
		}
	}

	error();
	lua_pop(m_state, 2); // Pop debug.traceback
	return false;
}

//-----------------------------------------------------------------------------
bool LuaEnvironment::execute_string(const char* s)
{
	CE_ASSERT_NOT_NULL(s);

	lua_getglobal(m_state, "debug");
	lua_getfield(m_state, -1, "traceback");
	if (luaL_loadstring(m_state, s) == 0)
	{
		if (lua_pcall(m_state, 0, 0, -2) == 0)
		{
			// Unloading is OK since the script data has been copied to Lua
			lua_pop(m_state, 2); // Pop debug.traceback
			return true;
		}
	}

	error();
	lua_pop(m_state, 2); // Pop debug.traceback
	return false;
}

//-----------------------------------------------------------------------------
void LuaEnvironment::load_module_function(const char* module, const char* name, const lua_CFunction func)
{
	luaL_Reg entry[2];

	entry[0].name = name;
	entry[0].func = func;
	entry[1].name = NULL;
	entry[1].func = NULL;

	luaL_register(m_state, module, entry);
}

//-----------------------------------------------------------
void LuaEnvironment::load_module_enum(const char* /*module*/, const char* name, uint32_t value)
{
	lua_pushinteger(m_state, value);
	lua_setfield(m_state, -2, name);
}

//-----------------------------------------------------------------------------
bool LuaEnvironment::call_global(const char* func, uint8_t argc, ...)
{
	CE_ASSERT_NOT_NULL(func);

	LuaStack stack(m_state);

	va_list vl;
	va_start(vl, argc);

	lua_getglobal(m_state, "debug");
	lua_getfield(m_state, -1, "traceback");
	lua_getglobal(m_state, func);

	for (uint8_t i = 0; i < argc; i++)
	{
		const int type = va_arg(vl, int);
		switch (type)
		{
			case ARGUMENT_FLOAT:
			{
				stack.push_float(va_arg(vl, double));
				break;
			}
			default:
			{
				CE_ASSERT(false, "Oops, lua argument unknown");
				break;
			}
		}
	}

	va_end(vl);

	if (lua_pcall(m_state, argc, 0, -argc - 2) != 0)
	{
		error();
		lua_pop(m_state, 2); // Pop debug.traceback
		return false;
	}

	lua_pop(m_state, 2); // Pop debug.traceback

	return true;
}

//-----------------------------------------------------------------------------
void LuaEnvironment::error()
{
	const char* msg = lua_tostring(m_state, -1);
	Log::e(msg);
	lua_pop(m_state, 1);
}

} // namespace crown<|endoftext|>


<commit_before>// Copyright (C) 2019 by Joseph Mirabel, LAAS-CNRS.
//
// This file is part of the hpp-corbaserver.
//
// This software is provided "as is" without warranty of any kind,
// either expressed or implied, including but not limited to the
// implied warranties of fitness for a particular purpose.
//
// See the COPYING file for more information.

#ifndef SRC_PATH_VALIATIONS_HH
# define SRC_PATH_VALIATIONS_HH

# include <vector>
# include <stdlib.h>

# include "hpp/core/path-validation.hh"

# include <hpp/corbaserver/fwd.hh>
# include <hpp/corbaserver/conversions.hh>
# include "hpp/core_idl/path_validations-idl.hh"

# include "../servant-base.hh"

namespace hpp
{
  namespace corbaServer
  {
    namespace core_idl
    {
      typedef AbstractServantBase<core::PathValidationPtr_t> PathValidationBase;

      template <typename D>
      struct PathValidationStorage {
        D d;
        PathValidationStorage (const D& _d) : d(_d) {}
        operator core::PathValidationPtr_t () const { return d; }
      };

      template <typename Base, typename _Storage>
      class PathValidationServant : public PathValidationBase, public virtual Base
      {
        public:
          typedef _Storage Storage;

          PathValidationServant (Server* server, const Storage& s) :
            PathValidationBase (server), s_ (s) {}

          virtual ~PathValidationServant () {}

          CORBA::Boolean validate (hpp::core_idl::Path_ptr path,
              CORBA::Boolean reverse,
              hpp::core_idl::Path_out validPart,
              hpp::core_idl::PathValidationReport_out report) throw (Error)
          {
            core::PathPtr_t p (reference_to_servant_base<core::PathPtr_t>(server_, path)->get());
            core::PathPtr_t vp;
            core::PathValidationReportPtr_t pvr;

            bool res = get()->validate (p, reverse, vp, pvr);

            if (pvr) {
              std::ostringstream oss; oss << *pvr;
              std::string res = oss.str();
              report = CORBA::string_dup(res.c_str());
            } else {
              report = CORBA::string_dup("");
            }

            validPart = makeServant<hpp::core_idl::Path_ptr> (server_, new Path (server_, vp));
            return res;
          }

          virtual core::PathValidationPtr_t get ()
          {
            return (core::PathValidationPtr_t)s_;
          }

          Storage getS ()
          {
            return s_;
          }

        protected:
          Storage s_;
      };

      typedef PathValidationServant<POA_hpp::core_idl::PathValidation, PathValidationStorage<core::PathValidationPtr_t> > PathValidation;

    } // end of namespace core.
  } // end of namespace corbaServer.
} // end of namespace hpp.

#endif // SRC_PATH_VALIATIONS_HH
<commit_msg>Rework path validations.<commit_after>// Copyright (C) 2019 by Joseph Mirabel, LAAS-CNRS.
//
// This file is part of the hpp-corbaserver.
//
// This software is provided "as is" without warranty of any kind,
// either expressed or implied, including but not limited to the
// implied warranties of fitness for a particular purpose.
//
// See the COPYING file for more information.

#ifndef SRC_PATH_VALIATIONS_HH
# define SRC_PATH_VALIATIONS_HH

# include <vector>
# include <stdlib.h>

# include "hpp/core/path-validation.hh"

# include <hpp/corbaserver/fwd.hh>
# include <hpp/corbaserver/conversions.hh>
# include "hpp/core_idl/path_validations-idl.hh"

# include "../servant-base.hh"

namespace hpp
{
  namespace corbaServer
  {
    namespace core_idl
    {
      typedef AbstractServantBase<core::PathValidationPtr_t> PathValidationBase;

      template <typename _Base, typename _Storage>
      class PathValidationServant : public PathValidationBase, public virtual _Base
      {
        public:
          typedef _Base    Base;
          typedef _Storage Storage;
          SERVANT_BASE_TYPEDEFS(hpp::core_idl::PathValidation)

          PathValidationServant (Server* server, const Storage& s) :
            PathValidationBase (server), s_ (s) {}

          virtual ~PathValidationServant () {}

          CORBA::Boolean validate (hpp::core_idl::Path_ptr path,
              CORBA::Boolean reverse,
              hpp::core_idl::Path_out validPart,
              hpp::core_idl::PathValidationReport_out report) throw (Error)
          {
            core::PathPtr_t p (reference_to_servant_base<core::PathPtr_t>(server_, path)->get());
            core::PathPtr_t vp;
            core::PathValidationReportPtr_t pvr;

            bool res = get()->validate (p, reverse, vp, pvr);

            if (pvr) {
              std::ostringstream oss; oss << *pvr;
              std::string res = oss.str();
              report = CORBA::string_dup(res.c_str());
            } else {
              report = CORBA::string_dup("");
            }

            validPart = makeServant<hpp::core_idl::Path_ptr> (server_, new Path (server_, vp));
            return res;
          }

          virtual core::PathValidationPtr_t get ()
          {
            return (core::PathValidationPtr_t)s_;
          }

          Storage getS ()
          {
            return s_;
          }

        protected:
          Storage s_;
      };

      typedef PathValidationServant<POA_hpp::core_idl::PathValidation, core::PathValidationPtr_t > PathValidation;

      typedef boost::mpl::vector<PathValidation> PathValidations;

    } // end of namespace core.
  } // end of namespace corbaServer.
} // end of namespace hpp.

#endif // SRC_PATH_VALIATIONS_HH
<|endoftext|>


<commit_before>/*
 * ServerOptions.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <server/ServerOptions.hpp>

#include <core/ProgramStatus.hpp>
#include <core/ProgramOptions.hpp>
#include <core/FilePath.hpp>

#include <core/system/PosixUser.hpp>
#include <core/system/PosixSystem.hpp>

#include "ServerAppArmor.hpp"

using namespace core ;

namespace server {

namespace {

const char * const kDefaultProgramUser = "rstudio-server";

} // anonymous namespace

Options& options()
{
   static Options instance ;
   return instance ;
}

ProgramStatus Options::read(int argc, char * const argv[])
{
   using namespace boost::program_options ;

   // compute install path
   Error error = core::system::installPath("..", argc, argv, &installPath_);
   if (error)
   {
      LOG_ERROR_MESSAGE("Unable to determine install path: "+error.summary());
      return ProgramStatus::exitFailure();
   }

   // verify installation flag
   options_description verify("verify");
   verify.add_options()
     ("verify-installation",
     value<bool>(&verifyInstallation_)->default_value(false),
     "verify the current installation");

   // special program offline option (based on file existence at
   // startup for easy bash script enable/disable of offline state)
   serverOffline_ = FilePath("/var/lib/rstudio-server/offline").exists();

   // program - name and execution
   options_description server("server");
   server.add_options()
      ("server-working-dir",
         value<std::string>(&serverWorkingDir_)->default_value("/"),
         "program working directory")
      ("server-user",
         value<std::string>(&serverUser_)->default_value(kDefaultProgramUser),
         "program user")
      ("server-daemonize",
         value<bool>(&serverDaemonize_)->default_value(1),
         "run program as daemon")
      ("server-app-armor-enabled",
         value<bool>(&serverAppArmorEnabled_)->default_value(1),
         "is app armor enabled for this session");

   // www - web server options
   options_description www("www") ;
   www.add_options()
      ("www-address",
         value<std::string>(&wwwAddress_)->default_value("0.0.0.0"),
         "server address")
      ("www-port",
         value<std::string>(&wwwPort_)->default_value(""),
         "port to listen on")
      ("www-local-path",
         value<std::string>(&wwwLocalPath_)->default_value("www"),
         "www files path")
      ("www-thread-pool-size",
         value<int>(&wwwThreadPoolSize_)->default_value(2),
         "thread pool size");

   // rsession
   options_description rsession("rsession");
   rsession.add_options()
      ("rsession-which-r",
         value<std::string>(&rsessionWhichR_)->default_value(""),
         "path to main R program (e.g. /usr/bin/R)")
      ("rsession-path",
         value<std::string>(&rsessionPath_)->default_value("bin/rsession"),
         "path to rsession executable")
      ("rldpath-path",
         value<std::string>(&rldpathPath_)->default_value("bin/r-ldpath"),
         "path to r-ldpath script")
      ("rsession-ld-library-path",
         value<std::string>(&rsessionLdLibraryPath_)->default_value(""),
         "default LD_LIBRARY_PATH for rsession")
      ("rsession-config-file",
         value<std::string>(&rsessionConfigFile_)->default_value(""),
         "path to rsession config file")
      ("rsession-memory-limit-mb",
         value<int>(&rsessionMemoryLimitMb_)->default_value(0),
         "rsession memory limit (mb)")
      ("rsession-stack-limit-mb",
         value<int>(&rsessionStackLimitMb_)->default_value(0),
         "rsession stack limit (mb)")
      ("rsession-process-limit",
         value<int>(&rsessionUserProcessLimit_)->default_value(0),
         "rsession user process limit");

   // still read depracated options (so we don't break config files)
   bool deprecatedAuthPamRequiresPriv;
   options_description auth("auth");
   auth.add_options()
      ("auth-validate-users",
        value<bool>(&authValidateUsers_)->default_value(true),
        "validate that authenticated users exist on the target system")
      ("auth-required-user-group",
        value<std::string>(&authRequiredUserGroup_)->default_value(""),
        "limit to users belonging to the specified group")
      ("auth-pam-helper-path",
        value<std::string>(&authPamHelperPath_)->default_value("bin/rserver-pam"),
       "path to PAM helper binary")
      ("auth-pam-requires-priv",
        value<bool>(&deprecatedAuthPamRequiresPriv)->default_value(true),
        "deprecated: will always be true");

   // define program options
   FilePath defaultConfigPath("/etc/rstudio/rserver.conf");
   std::string configFile = defaultConfigPath.exists() ?
                                 defaultConfigPath.absolutePath() : "";
   program_options::OptionsDescription optionsDesc("rserver", configFile);

   // overlay hooks
   addOverlayOptions(&server, &www, &rsession, &auth);
   resolveOverlayOptions();

   // overlay validation
   std::string errMsg;
   if (!validateOverlayOptions(&errMsg))
   {
      LOG_ERROR_MESSAGE(errMsg);
      return ProgramStatus::exitFailure();
   }

   optionsDesc.commandLine.add(verify).add(server).add(www).add(rsession).add(auth);
   optionsDesc.configFile.add(server).add(www).add(rsession).add(auth);

   // read options
   ProgramStatus status = core::program_options::read(optionsDesc, argc, argv);
   if (status.exit())
      return status;

   // if specified, confirm that the program user exists. however, if the
   // program user is the default and it doesn't exist then allow that to pass,
   // this just means that the user did a simple make install and hasn't setup
   // an rserver user yet. in this case the program will run as root
   if (!serverUser_.empty())
   {
      // if we aren't running as root then forget the programUser
      if (!core::system::realUserIsRoot())
      {
         serverUser_ = "";
      }
      // if there is a program user specified and it doesn't exist....
      else if (!core::system::user::exists(serverUser_))
      {
         if (serverUser_ == kDefaultProgramUser)
         {
            // administrator hasn't created an rserver system account yet
            // so we'll end up running as root
            serverUser_ = "";
         }
         else
         {
            LOG_ERROR_MESSAGE("Server user "+ serverUser_ +" does not exist");
            return ProgramStatus::exitFailure();
         }
      }
   }

   // if app armor is enabled do a further check to see whether
   // the profile exists. if it doesn't then disable it
   if (serverAppArmorEnabled_)
   {
      if (!FilePath("/etc/apparmor.d/rstudio-server").exists())
         serverAppArmorEnabled_ = false;
   }

   // convert relative paths by completing from the system installation
   // path (this allows us to be relocatable)
   resolvePath(&wwwLocalPath_);
   resolvePath(&authPamHelperPath_);
   resolvePath(&rsessionPath_);
   resolvePath(&rldpathPath_);
   resolvePath(&rsessionConfigFile_);

   // return status
   return status;
}

void Options::resolvePath(std::string* pPath) const
{
   if (!pPath->empty())
      *pPath = installPath_.complete(*pPath).absolutePath();
}

} // namespace server
<commit_msg>Revert "resolve and validate overlay options sooner"<commit_after>/*
 * ServerOptions.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <server/ServerOptions.hpp>

#include <core/ProgramStatus.hpp>
#include <core/ProgramOptions.hpp>
#include <core/FilePath.hpp>

#include <core/system/PosixUser.hpp>
#include <core/system/PosixSystem.hpp>

#include "ServerAppArmor.hpp"

using namespace core ;

namespace server {

namespace {

const char * const kDefaultProgramUser = "rstudio-server";

} // anonymous namespace

Options& options()
{
   static Options instance ;
   return instance ;
}

ProgramStatus Options::read(int argc, char * const argv[])
{
   using namespace boost::program_options ;

   // compute install path
   Error error = core::system::installPath("..", argc, argv, &installPath_);
   if (error)
   {
      LOG_ERROR_MESSAGE("Unable to determine install path: "+error.summary());
      return ProgramStatus::exitFailure();
   }

   // verify installation flag
   options_description verify("verify");
   verify.add_options()
     ("verify-installation",
     value<bool>(&verifyInstallation_)->default_value(false),
     "verify the current installation");

   // special program offline option (based on file existence at
   // startup for easy bash script enable/disable of offline state)
   serverOffline_ = FilePath("/var/lib/rstudio-server/offline").exists();

   // program - name and execution
   options_description server("server");
   server.add_options()
      ("server-working-dir",
         value<std::string>(&serverWorkingDir_)->default_value("/"),
         "program working directory")
      ("server-user",
         value<std::string>(&serverUser_)->default_value(kDefaultProgramUser),
         "program user")
      ("server-daemonize",
         value<bool>(&serverDaemonize_)->default_value(1),
         "run program as daemon")
      ("server-app-armor-enabled",
         value<bool>(&serverAppArmorEnabled_)->default_value(1),
         "is app armor enabled for this session");

   // www - web server options
   options_description www("www") ;
   www.add_options()
      ("www-address",
         value<std::string>(&wwwAddress_)->default_value("0.0.0.0"),
         "server address")
      ("www-port",
         value<std::string>(&wwwPort_)->default_value(""),
         "port to listen on")
      ("www-local-path",
         value<std::string>(&wwwLocalPath_)->default_value("www"),
         "www files path")
      ("www-thread-pool-size",
         value<int>(&wwwThreadPoolSize_)->default_value(2),
         "thread pool size");

   // rsession
   options_description rsession("rsession");
   rsession.add_options()
      ("rsession-which-r",
         value<std::string>(&rsessionWhichR_)->default_value(""),
         "path to main R program (e.g. /usr/bin/R)")
      ("rsession-path",
         value<std::string>(&rsessionPath_)->default_value("bin/rsession"),
         "path to rsession executable")
      ("rldpath-path",
         value<std::string>(&rldpathPath_)->default_value("bin/r-ldpath"),
         "path to r-ldpath script")
      ("rsession-ld-library-path",
         value<std::string>(&rsessionLdLibraryPath_)->default_value(""),
         "default LD_LIBRARY_PATH for rsession")
      ("rsession-config-file",
         value<std::string>(&rsessionConfigFile_)->default_value(""),
         "path to rsession config file")
      ("rsession-memory-limit-mb",
         value<int>(&rsessionMemoryLimitMb_)->default_value(0),
         "rsession memory limit (mb)")
      ("rsession-stack-limit-mb",
         value<int>(&rsessionStackLimitMb_)->default_value(0),
         "rsession stack limit (mb)")
      ("rsession-process-limit",
         value<int>(&rsessionUserProcessLimit_)->default_value(0),
         "rsession user process limit");

   // still read depracated options (so we don't break config files)
   bool deprecatedAuthPamRequiresPriv;
   options_description auth("auth");
   auth.add_options()
      ("auth-validate-users",
        value<bool>(&authValidateUsers_)->default_value(true),
        "validate that authenticated users exist on the target system")
      ("auth-required-user-group",
        value<std::string>(&authRequiredUserGroup_)->default_value(""),
        "limit to users belonging to the specified group")
      ("auth-pam-helper-path",
        value<std::string>(&authPamHelperPath_)->default_value("bin/rserver-pam"),
       "path to PAM helper binary")
      ("auth-pam-requires-priv",
        value<bool>(&deprecatedAuthPamRequiresPriv)->default_value(true),
        "deprecated: will always be true");

   // define program options
   FilePath defaultConfigPath("/etc/rstudio/rserver.conf");
   std::string configFile = defaultConfigPath.exists() ?
                                 defaultConfigPath.absolutePath() : "";
   program_options::OptionsDescription optionsDesc("rserver", configFile);

   // overlay hook
   addOverlayOptions(&server, &www, &rsession, &auth);

   optionsDesc.commandLine.add(verify).add(server).add(www).add(rsession).add(auth);
   optionsDesc.configFile.add(server).add(www).add(rsession).add(auth);

   // read options
   ProgramStatus status = core::program_options::read(optionsDesc, argc, argv);
   if (status.exit())
      return status;

   // if specified, confirm that the program user exists. however, if the
   // program user is the default and it doesn't exist then allow that to pass,
   // this just means that the user did a simple make install and hasn't setup
   // an rserver user yet. in this case the program will run as root
   if (!serverUser_.empty())
   {
      // if we aren't running as root then forget the programUser
      if (!core::system::realUserIsRoot())
      {
         serverUser_ = "";
      }
      // if there is a program user specified and it doesn't exist....
      else if (!core::system::user::exists(serverUser_))
      {
         if (serverUser_ == kDefaultProgramUser)
         {
            // administrator hasn't created an rserver system account yet
            // so we'll end up running as root
            serverUser_ = "";
         }
         else
         {
            LOG_ERROR_MESSAGE("Server user "+ serverUser_ +" does not exist");
            return ProgramStatus::exitFailure();
         }
      }
   }

   // if app armor is enabled do a further check to see whether
   // the profile exists. if it doesn't then disable it
   if (serverAppArmorEnabled_)
   {
      if (!FilePath("/etc/apparmor.d/rstudio-server").exists())
         serverAppArmorEnabled_ = false;
   }

   // convert relative paths by completing from the system installation
   // path (this allows us to be relocatable)
   resolvePath(&wwwLocalPath_);
   resolvePath(&authPamHelperPath_);
   resolvePath(&rsessionPath_);
   resolvePath(&rldpathPath_);
   resolvePath(&rsessionConfigFile_);

   // overlay hook
   resolveOverlayOptions();

   // overlay validation
   std::string errMsg;
   if (!validateOverlayOptions(&errMsg))
   {
      LOG_ERROR_MESSAGE(errMsg);
      return ProgramStatus::exitFailure();
   }

   // return status
   return status;
}

void Options::resolvePath(std::string* pPath) const
{
   if (!pPath->empty())
      *pPath = installPath_.complete(*pPath).absolutePath();
}

} // namespace server
<|endoftext|>


<commit_before>#ifndef ITER_ENUMERATE_H_
#define ITER_ENUMERATE_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <functional>
#include <initializer_list>
#include <iterator>
#include <tuple>
#include <type_traits>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Index, typename Elem>
    using EnumBasePair = std::pair<Index, Elem>;

    // "yielded" by the Enumerable::Iterator.  Has a .index, and a
    // .element referencing the value yielded by the subiterator
    template <typename Index, typename Elem>
    class EnumIterYield : public EnumBasePair<Index, Elem> {
      using BasePair = EnumBasePair<Index, Elem>;
      using BasePair::BasePair;
      typename BasePair::first_type& index = BasePair::first;
      typename BasePair::second_type& element = BasePair::second;
    };

    template <typename Container, typename Index>
    class Enumerable;

    using EnumerateFn = IterToolFnOptionalBindSecond<Enumerable, std::size_t>;
  }
  constexpr impl::EnumerateFn enumerate{};
}

namespace std {
  template <typename Index, typename Elem>
  class tuple_size<iter::impl::EnumIterYield<Index, Elem>>
      : public tuple_size<iter::impl::EnumBasePair<Index, Elem>> {};

  template <std::size_t N, typename Index, typename Elem>
  class tuple_element<N, iter::impl::EnumIterYield<Index, Elem>>
      : public tuple_element<N, iter::impl::EnumBasePair<Index, Elem>> {};
}

template <typename Container, typename Index>
class iter::impl::Enumerable {
 private:
  Container container_;
  const Index start_;

  friend EnumerateFn;

  // Value constructor for use only in the enumerate function
  Enumerable(Container&& container, Index start)
      : container_(std::forward<Container>(container)), start_{start} {}

 public:
  Enumerable(Enumerable&&) = default;

  using IterYield = EnumIterYield<Index, iterator_deref<Container>>;

  //  Holds an iterator of the contained type and an Index for the
  //  index_.  Each call to ++ increments both of these data members.
  //  Each dereference returns an IterYield.
  class Iterator : public std::iterator<std::input_iterator_tag, IterYield> {
   private:
    IteratorWrapper<Container> sub_iter_;
    Index index_;

   public:
    Iterator(IteratorWrapper<Container>&& sub_iter, Index start)
        : sub_iter_{std::move(sub_iter)}, index_{start} {}

    IterYield operator*() {
      return {index_, *sub_iter_};
    }

    ArrowProxy<IterYield> operator->() {
      return {**this};
    }

    Iterator& operator++() {
      ++sub_iter_;
      ++index_;
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return sub_iter_ != other.sub_iter_;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }
  };

  Iterator begin() {
    return {get_begin(container_), start_};
  }

  Iterator end() {
    return {get_end(container_), start_};
  }
};
#endif
<commit_msg>Make index and element public in enumerate<commit_after>#ifndef ITER_ENUMERATE_H_
#define ITER_ENUMERATE_H_

#include "internal/iterator_wrapper.hpp"
#include "internal/iterbase.hpp"

#include <functional>
#include <initializer_list>
#include <iterator>
#include <tuple>
#include <type_traits>
#include <utility>

namespace iter {
  namespace impl {
    template <typename Index, typename Elem>
    using EnumBasePair = std::pair<Index, Elem>;

    // "yielded" by the Enumerable::Iterator.  Has a .index, and a
    // .element referencing the value yielded by the subiterator
    template <typename Index, typename Elem>
    class EnumIterYield : public EnumBasePair<Index, Elem> {
      using BasePair = EnumBasePair<Index, Elem>;
      using BasePair::BasePair;

     public:
      typename BasePair::first_type& index = BasePair::first;
      typename BasePair::second_type& element = BasePair::second;
    };

    template <typename Container, typename Index>
    class Enumerable;

    using EnumerateFn = IterToolFnOptionalBindSecond<Enumerable, std::size_t>;
  }
  constexpr impl::EnumerateFn enumerate{};
}

namespace std {
  template <typename Index, typename Elem>
  class tuple_size<iter::impl::EnumIterYield<Index, Elem>>
      : public tuple_size<iter::impl::EnumBasePair<Index, Elem>> {};

  template <std::size_t N, typename Index, typename Elem>
  class tuple_element<N, iter::impl::EnumIterYield<Index, Elem>>
      : public tuple_element<N, iter::impl::EnumBasePair<Index, Elem>> {};
}

template <typename Container, typename Index>
class iter::impl::Enumerable {
 private:
  Container container_;
  const Index start_;

  friend EnumerateFn;

  // Value constructor for use only in the enumerate function
  Enumerable(Container&& container, Index start)
      : container_(std::forward<Container>(container)), start_{start} {}

 public:
  Enumerable(Enumerable&&) = default;

  using IterYield = EnumIterYield<Index, iterator_deref<Container>>;

  //  Holds an iterator of the contained type and an Index for the
  //  index_.  Each call to ++ increments both of these data members.
  //  Each dereference returns an IterYield.
  class Iterator : public std::iterator<std::input_iterator_tag, IterYield> {
   private:
    IteratorWrapper<Container> sub_iter_;
    Index index_;

   public:
    Iterator(IteratorWrapper<Container>&& sub_iter, Index start)
        : sub_iter_{std::move(sub_iter)}, index_{start} {}

    IterYield operator*() {
      return {index_, *sub_iter_};
    }

    ArrowProxy<IterYield> operator->() {
      return {**this};
    }

    Iterator& operator++() {
      ++sub_iter_;
      ++index_;
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return sub_iter_ != other.sub_iter_;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }
  };

  Iterator begin() {
    return {get_begin(container_), start_};
  }

  Iterator end() {
    return {get_end(container_), start_};
  }
};
#endif
<|endoftext|>


<commit_before>
#include "rtkThreeDCircularProjectionGeometryXMLFile.h"
#include "rtkRayBoxIntersectionImageFilter.h"
#include "rtkJosephForwardProjectionImageFilter.h"
#include "rtkSheppLoganPhantomFilter.h"
#include "rtkDrawSheppLoganFilter.h"
#include "rtkConstantImageSource.h"

template<class TImage>
void CheckImageQuality(typename TImage::Pointer recon, typename TImage::Pointer ref)
{
  typedef itk::ImageRegionConstIterator<TImage> ImageIteratorType;
  ImageIteratorType itTest( recon, recon->GetBufferedRegion() );
  ImageIteratorType itRef( ref, ref->GetBufferedRegion() );

  typedef double ErrorType;
  ErrorType TestError = 0.;
  ErrorType EnerError = 0.;

  itTest.GoToBegin();
  itRef.GoToBegin();

  while( !itRef.IsAtEnd() )
    {
    typename TImage::PixelType TestVal = itTest.Get();
    typename TImage::PixelType RefVal = itRef.Get();

    if( TestVal != RefVal )
      {
      TestError += vcl_abs(RefVal - TestVal);
      EnerError += vcl_pow(ErrorType(RefVal - TestVal), 2.);
      }
    ++itTest;
    ++itRef;
    }
  // Error per Pixel
  ErrorType ErrorPerPixel = TestError/recon->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "\nError per Pixel = " << ErrorPerPixel << std::endl;
  // MSE
  ErrorType MSE = EnerError/ref->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "MSE = " << MSE << std::endl;
  // PSNR
  ErrorType PSNR = 20*log10(255.0) - 10*log10(MSE);
  std::cout << "PSNR = " << PSNR << "dB" << std::endl;
  // QI
  ErrorType QI = (255.0-ErrorPerPixel)/255.0;
  std::cout << "QI = " << QI << std::endl;

  // Checking results
  if (ErrorPerPixel > 1.28)
    {
    std::cerr << "Test Failed, Error per pixel not valid! "
              << ErrorPerPixel << " instead of 1.28" << std::endl;
    exit( EXIT_FAILURE);
    }
  if (PSNR < 44.)
    {
    std::cerr << "Test Failed, PSNR not valid! "
              << PSNR << " instead of 44" << std::endl;
    exit( EXIT_FAILURE);
    }
}

int main(int , char** )
{
  const unsigned int Dimension = 3;
  typedef float                                    OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::Vector<double, 3>                   VectorType;
  const unsigned int NumberOfProjectionImages = 45;

  // Constant image sources
  typedef rtk::ConstantImageSource< OutputImageType > ConstantImageSourceType;
  ConstantImageSourceType::PointType origin;
  ConstantImageSourceType::SizeType size;
  ConstantImageSourceType::SpacingType spacing;

  // The test projects a volume filled with ones. The forward projector should
  // then return the intersection of the ray with the box and it is compared
  // with the analytical intersection of a box with a ray.

  // Create Joseph Forward Projector volume input.
  const ConstantImageSourceType::Pointer volInput = ConstantImageSourceType::New();
  origin[0] = -126;
  origin[1] = -126;
  origin[2] = -126;
  size[0] = 64;
  size[1] = 64;
  size[2] = 64;
  spacing[0] = 4.;
  spacing[1] = 4.;
  spacing[2] = 4.;
  volInput->SetOrigin( origin );
  volInput->SetSpacing( spacing );
  volInput->SetSize( size );
  volInput->SetConstant( 1. );
  volInput->UpdateOutputInformation();

  // Initialization Volume, it is used in the Joseph Forward Projector and in the
  // Ray Box Intersection Filter in order to initialize the stack of projections.
  const ConstantImageSourceType::Pointer projInput = ConstantImageSourceType::New();
  size[2] = NumberOfProjectionImages;
  projInput->SetOrigin( origin );
  projInput->SetSpacing( spacing );
  projInput->SetSize( size );
  projInput->SetConstant( 0. );
  projInput->Update();

  // Joseph Forward Projection filter
  typedef rtk::JosephForwardProjectionImageFilter<OutputImageType, OutputImageType> JFPType;
  JFPType::Pointer jfp = JFPType::New();
  jfp->InPlaceOff();
  jfp->SetInput( projInput->GetOutput() );
  jfp->SetInput( 1, volInput->GetOutput() );

  // Ray Box Intersection filter (reference)
  typedef rtk::RayBoxIntersectionImageFilter<OutputImageType, OutputImageType> RBIType;
  RBIType::Pointer rbi = RBIType::New();
  rbi->InPlaceOff();
  rbi->SetInput( projInput->GetOutput() );
  VectorType boxMin, boxMax;
  boxMin[0] = -128.0;
  boxMin[1] = -128.0;
  boxMin[2] = -128.0;
  boxMax[0] =  128.0;
  boxMax[1] =  128.0;
  boxMax[2] =   47.6;
  rbi->SetBoxMin(boxMin);
  rbi->SetBoxMax(boxMax);

  std::cout << "\n\n****** Case 1: inner ray source ******" << std::endl;
  // The circle is divided in 4 quarters
  for(int q=0; q<4; q++) {
    // Geometry
    typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
    GeometryType::Pointer geometry = GeometryType::New();
    for(unsigned int i=0; i<NumberOfProjectionImages;i++)
      {
      const double angle = -45. + i*2.;
      geometry->AddProjection(47.6 / vcl_cos(angle*itk::Math::pi/180.), 1000., q*90+angle);
      }

    if(q==0) {
      rbi->SetGeometry( geometry );
      rbi->Update();
    }

    jfp->SetGeometry(geometry);
    jfp->Update();

    CheckImageQuality<OutputImageType>(rbi->GetOutput(), jfp->GetOutput());
    std::cout << "\n\nTest of quarter #" << q << " PASSED! " << std::endl;
  }

  std::cout << "\n\n****** Case 2: outer ray source ******" << std::endl;
  boxMax[2] = 128.0;
  rbi->SetBoxMax(boxMax);

  // Geometry
  typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
  GeometryType::Pointer geometry = GeometryType::New();
  for(unsigned int i=0; i<NumberOfProjectionImages; i++)
    geometry->AddProjection(500., 1000., i*8.);

  rbi->SetGeometry( geometry );
  rbi->Update();

  jfp->SetGeometry( geometry );
  jfp->Update();

  CheckImageQuality<OutputImageType>(rbi->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  std::cout << "\n\n****** Case 3: Shepp-Logan, outer ray source ******" << std::endl;

  // Create Shepp Logan reference projections
  typedef rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType> SLPType;
  SLPType::Pointer slp = SLPType::New();
  slp->InPlaceOff();
  slp->SetInput( projInput->GetOutput() );
  slp->SetGeometry(geometry);
  slp->Update();

  // Create a Shepp Logan reference volume (finer resolution)
  origin.Fill(-127);
  size.Fill(128);
  spacing.Fill(2.);
  volInput->SetOrigin( origin );
  volInput->SetSpacing( spacing );
  volInput->SetSize( size );
  volInput->SetConstant( 0. );

  typedef rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType> DSLType;
  DSLType::Pointer dsl = DSLType::New();
  dsl->InPlaceOff();
  dsl->SetInput( volInput->GetOutput() );
  dsl->Update();

  // Forward projection
  jfp->SetInput( 1, dsl->GetOutput() );
  jfp->Update();

  CheckImageQuality<OutputImageType>(slp->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  std::cout << "\n\n****** Case 4: Shepp-Logan, inner ray source ******" << std::endl;
  geometry = GeometryType::New();
  for(unsigned int i=0; i<NumberOfProjectionImages; i++)
    geometry->AddProjection(120., 1000., i*8.);

  slp->SetGeometry(geometry);
  slp->Update();

  jfp->SetGeometry( geometry );
  jfp->Update();

  CheckImageQuality<OutputImageType>(slp->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  return EXIT_SUCCESS;
}
<commit_msg>Cuda forward projector added<commit_after>
#include "rtkThreeDCircularProjectionGeometryXMLFile.h"
#include "rtkRayBoxIntersectionImageFilter.h"
#include "rtkSheppLoganPhantomFilter.h"
#include "rtkDrawSheppLoganFilter.h"
#include "rtkConstantImageSource.h"

#ifdef USE_CUDA
#  include "rtkCudaForwardProjectionImageFilter.h"
#else
#  include "rtkJosephForwardProjectionImageFilter.h"
#endif

#include <itkImageFileWriter.h>

template<class TImage>
void CheckImageQuality(typename TImage::Pointer recon, typename TImage::Pointer ref)
{
  typedef itk::ImageRegionConstIterator<TImage> ImageIteratorType;
  ImageIteratorType itTest( recon, recon->GetBufferedRegion() );
  ImageIteratorType itRef( ref, ref->GetBufferedRegion() );

  typedef double ErrorType;
  ErrorType TestError = 0.;
  ErrorType EnerError = 0.;

  itTest.GoToBegin();
  itRef.GoToBegin();

  while( !itRef.IsAtEnd() )
    {
    typename TImage::PixelType TestVal = itTest.Get();
    typename TImage::PixelType RefVal = itRef.Get();

    if( TestVal != RefVal )
      {
      TestError += vcl_abs(RefVal - TestVal);
      EnerError += vcl_pow(ErrorType(RefVal - TestVal), 2.);
      }
    ++itTest;
    ++itRef;
    }
  // Error per Pixel
  ErrorType ErrorPerPixel = TestError/recon->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "\nError per Pixel = " << ErrorPerPixel << std::endl;
  // MSE
  ErrorType MSE = EnerError/ref->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "MSE = " << MSE << std::endl;
  // PSNR
  ErrorType PSNR = 20*log10(255.0) - 10*log10(MSE);
  std::cout << "PSNR = " << PSNR << "dB" << std::endl;
  // QI
  ErrorType QI = (255.0-ErrorPerPixel)/255.0;
  std::cout << "QI = " << QI << std::endl;

  // Checking results
#ifndef USE_CUDA
  if (ErrorPerPixel > 1.28)
    {
    std::cerr << "Test Failed, Error per pixel not valid! "
              << ErrorPerPixel << " instead of 1.28" << std::endl;
    exit( EXIT_FAILURE);
    }
  if (PSNR < 44.)
    {
    std::cerr << "Test Failed, PSNR not valid! "
              << PSNR << " instead of 44" << std::endl;
    exit( EXIT_FAILURE);
    }
#else
  if (ErrorPerPixel > 3.)
    {
    std::cerr << "Test Failed, Error per pixel not valid! "
              << ErrorPerPixel << " instead of 3." << std::endl;
    exit( EXIT_FAILURE);
    }
  if (PSNR < 40.)
    {
    std::cerr << "Test Failed, PSNR not valid! "
              << PSNR << " instead of 40" << std::endl;
    exit( EXIT_FAILURE);
    }
#endif
}

int main(int , char** argv)
{
  const unsigned int Dimension = 3;
  typedef float                                    OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::Vector<double, 3>                   VectorType;
  const unsigned int NumberOfProjectionImages = 45;

  // Constant image sources
  typedef rtk::ConstantImageSource< OutputImageType > ConstantImageSourceType;
  ConstantImageSourceType::PointType origin;
  ConstantImageSourceType::SizeType size;
  ConstantImageSourceType::SpacingType spacing;

  // The test projects a volume filled with ones. The forward projector should
  // then return the intersection of the ray with the box and it is compared
  // with the analytical intersection of a box with a ray.

  // Create Joseph Forward Projector volume input.
  const ConstantImageSourceType::Pointer volInput = ConstantImageSourceType::New();
  origin[0] = -126;
  origin[1] = -126;
  origin[2] = -126;
  size[0] = 64;
  size[1] = 64;
  size[2] = 64;
  spacing[0] = 4.;
  spacing[1] = 4.;
  spacing[2] = 4.;
  volInput->SetOrigin( origin );
  volInput->SetSpacing( spacing );
  volInput->SetSize( size );
  volInput->SetConstant( 1. );
  volInput->UpdateOutputInformation();

  // Initialization Volume, it is used in the Joseph Forward Projector and in the
  // Ray Box Intersection Filter in order to initialize the stack of projections.
  const ConstantImageSourceType::Pointer projInput = ConstantImageSourceType::New();
  size[2] = NumberOfProjectionImages;
  projInput->SetOrigin( origin );
  projInput->SetSpacing( spacing );
  projInput->SetSize( size );
  projInput->SetConstant( 0. );
  projInput->Update();

  // Joseph Forward Projection filter
#ifdef USE_CUDA
  typedef rtk::CudaForwardProjectionImageFilter JFPType;
#else
  typedef rtk::JosephForwardProjectionImageFilter<OutputImageType, OutputImageType> JFPType;
#endif
  JFPType::Pointer jfp = JFPType::New();
  jfp->InPlaceOff();
  jfp->SetInput( projInput->GetOutput() );
  jfp->SetInput( 1, volInput->GetOutput() );

  // Ray Box Intersection filter (reference)
  typedef rtk::RayBoxIntersectionImageFilter<OutputImageType, OutputImageType> RBIType;
  RBIType::Pointer rbi = RBIType::New();
  rbi->InPlaceOff();
  rbi->SetInput( projInput->GetOutput() );
  VectorType boxMin, boxMax;
  boxMin[0] = -128.0;
  boxMin[1] = -128.0;
  boxMin[2] = -128.0;
  boxMax[0] =  128.0;
  boxMax[1] =  128.0;
  boxMax[2] =   47.6;
  rbi->SetBoxMin(boxMin);
  rbi->SetBoxMax(boxMax);

  std::cout << "\n\n****** Case 1: inner ray source ******" << std::endl;
  // The circle is divided in 4 quarters
  for(int q=0; q<4; q++) {
    // Geometry
    typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
    GeometryType::Pointer geometry = GeometryType::New();
    for(unsigned int i=0; i<NumberOfProjectionImages;i++)
      {
      const double angle = -45. + i*2.;
      geometry->AddProjection(47.6 / vcl_cos(angle*itk::Math::pi/180.), 1000., q*90+angle);
      }

    if(q==0) {
      rbi->SetGeometry( geometry );
      rbi->Update();
    }

    jfp->SetGeometry(geometry);
    jfp->Update();

    CheckImageQuality<OutputImageType>(rbi->GetOutput(), jfp->GetOutput());
    std::cout << "\n\nTest of quarter #" << q << " PASSED! " << std::endl;
  }

  std::cout << "\n\n****** Case 2: outer ray source ******" << std::endl;
  boxMax[2] = 128.0;
  rbi->SetBoxMax(boxMax);

  // Geometry
  typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
  GeometryType::Pointer geometry = GeometryType::New();
  for(unsigned int i=0; i<NumberOfProjectionImages; i++)
    geometry->AddProjection(500., 1000., i*8.);

  rbi->SetGeometry( geometry );
  rbi->Update();

  jfp->SetGeometry( geometry );
  jfp->Update();

  CheckImageQuality<OutputImageType>(rbi->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  std::cout << "\n\n****** Case 3: Shepp-Logan, outer ray source ******" << std::endl;

  // Create Shepp Logan reference projections
  typedef rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType> SLPType;
  SLPType::Pointer slp = SLPType::New();
  slp->InPlaceOff();
  slp->SetInput( projInput->GetOutput() );
  slp->SetGeometry(geometry);
  slp->Update();

  // Create a Shepp Logan reference volume (finer resolution)
  origin.Fill(-127);
  size.Fill(128);
  spacing.Fill(2.);
  volInput->SetOrigin( origin );
  volInput->SetSpacing( spacing );
  volInput->SetSize( size );
  volInput->SetConstant( 0. );

  typedef rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType> DSLType;
  DSLType::Pointer dsl = DSLType::New();
  dsl->InPlaceOff();
  dsl->SetInput( volInput->GetOutput() );
  dsl->Update();

  // Forward projection
  jfp->SetInput( 1, dsl->GetOutput() );
  jfp->Update();

  CheckImageQuality<OutputImageType>(slp->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  std::cout << "\n\n****** Case 4: Shepp-Logan, inner ray source ******" << std::endl;
  geometry = GeometryType::New();
  for(unsigned int i=0; i<NumberOfProjectionImages; i++)
    geometry->AddProjection(120., 1000., i*8.);

  slp->SetGeometry(geometry);
  slp->Update();

  jfp->SetGeometry( geometry );
  jfp->Update();

  CheckImageQuality<OutputImageType>(slp->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * point.cpp
 *
 *  Created on: June 12, 2016
 *      Author: Tumblr
 */

#include <string>
#include <sstream>
#include "point.h"

using namespace std;

/*
 * Default Point constructor
 */
Point::Point() {
    x = 0;
    y = 0;
}

/*
 * Creates a Point with the given coordinates (x_coord, y_coord)
 */
Point::Point(int x_coord, int y_coord) {
    x = x_coord;
    y = y_coord;
}

/*
 * Point clone constructor
 */
Point::Point(const Point& clone) {
    // TODO
}

/*
 * Default Point destructor
 */
Point::~Point() {
    // TODO
}

/*
 * Checks if this point is equal to the given Point pnt.
 */
bool Point::equals(Point pnt) {
    // TODO
    if(pnt.x == x && pnt.y == y){
        return true;
    }
    return false;
}

/*
 * Returns the position of this Point as a Point.
 */
Point Point::get_location() {
    Point ret;
    // TODO
    ret.x = x;
    ret.y = y;
    return ret;
}

/*
 * Sets this point's coordinates equals to that of the
 * given Point (x_coord, y_coord).
 */
void Point::set_location(int x_coord, int y_coord) {
    // TODO
    x = x_coord;
    y = y_coord;
}

/*
 * Sets this point's coordinates equals to that of the
 * given Point pnt.
 */
void Point::set_location(Point pnt) {
    // TODO
    x = pnt.x;
    y = pnt.y;
}

/*
 * Returns this Point as a string in the format (x, y).
 */
string Point::to_string() {
    std::ostringstream ret;
    ret << "(" << x << "," << y << ")";
    return ret.str();
}

/*
 * Moves this Point by dx in the x direction and dy in the
 * y direction. The position of this Point becomes
 * (x + dx, y + dy).
 */
void Point::translate(int dx, int dy) {
    // TODO
    x = x + dx;
    y = y + dy;
}
<commit_msg>update to_string<commit_after>/*
 * point.cpp
 *
 *  Created on: June 12, 2016
 *      Author: Tumblr
 */

#include <string>
#include <sstream>
#include "point.h"

using namespace std;

/*
 * Default Point constructor
 */
Point::Point() {
    x = 0;
    y = 0;
}

/*
 * Creates a Point with the given coordinates (x_coord, y_coord)
 */
Point::Point(int x_coord, int y_coord) {
    x = x_coord;
    y = y_coord;
}

/*
 * Point clone constructor
 */
Point::Point(const Point& clone) {
    // TODO
}

/*
 * Default Point destructor
 */
Point::~Point() {
    // TODO
}

/*
 * Checks if this point is equal to the given Point pnt.
 */
bool Point::equals(Point pnt) {
    // TODO
    if(pnt.x == x && pnt.y == y){
        return true;
    }
    return false;
}

/*
 * Returns the position of this Point as a Point.
 */
Point Point::get_location() {
    Point ret;
    // TODO
    ret.x = x;
    ret.y = y;
    return ret;
}

/*
 * Sets this point's coordinates equals to that of the
 * given Point (x_coord, y_coord).
 */
void Point::set_location(int x_coord, int y_coord) {
    // TODO
    x = x_coord;
    y = y_coord;
}

/*
 * Sets this point's coordinates equals to that of the
 * given Point pnt.
 */
void Point::set_location(Point pnt) {
    // TODO
    x = pnt.x;
    y = pnt.y;
}

/*
 * Returns this Point as a string in the format (x, y).
 */
string Point::to_string() {
   string ret;
	ret += "(";
	ret += std::to_string(x)
	ret += ",";
	ret += std::to_string(y)
	ret += ")";

	return ret;
}
/*
 * Moves this Point by dx in the x direction and dy in the
 * y direction. The position of this Point becomes
 * (x + dx, y + dy).
 */
void Point::translate(int dx, int dy) {
    // TODO
    x = x + dx;
    y = y + dy;
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <mesos/type_utils.hpp>

#include <process/clock.hpp>
#include <process/pid.hpp>

#include <stout/net.hpp>
#include <stout/stringify.hpp>
#include <stout/uuid.hpp>

#include "messages/messages.hpp"

using std::string;

namespace mesos {
namespace internal {
namespace protobuf {

bool isTerminalState(const TaskState& state)
{
  return (state == TASK_FINISHED ||
          state == TASK_FAILED ||
          state == TASK_KILLED ||
          state == TASK_LOST ||
          state == TASK_ERROR);
}

// TODO(vinod): Make SlaveID optional because 'StatusUpdate.SlaveID'
// is optional.
StatusUpdate createStatusUpdate(
    const FrameworkID& frameworkId,
    const Option<SlaveID>& slaveId,
    const TaskID& taskId,
    const TaskState& state,
    const TaskStatus::Source& source,
    const string& message = "",
    const Option<TaskStatus::Reason>& reason = None(),
    const Option<ExecutorID>& executorId = None(),
    const Option<bool>& healthy = None())
{
  StatusUpdate update;

  update.set_timestamp(process::Clock::now().secs());
  update.set_uuid(UUID::random().toBytes());
  update.mutable_framework_id()->MergeFrom(frameworkId);

  if (slaveId.isSome()) {
    update.mutable_slave_id()->MergeFrom(slaveId.get());
  }

  if (executorId.isSome()) {
    update.mutable_executor_id()->MergeFrom(executorId.get());
  }

  TaskStatus* status = update.mutable_status();
  status->mutable_task_id()->MergeFrom(taskId);

  if (slaveId.isSome()) {
    status->mutable_slave_id()->MergeFrom(slaveId.get());
  }

  status->set_state(state);
  status->set_source(source);
  status->set_message(message);
  status->set_timestamp(update.timestamp());

  if (reason.isSome()) {
    status->set_reason(reason.get());
  }

  if (healthy.isSome()) {
    status->set_healthy(healthy.get());
  }

  return update;
}

Task createTask(
    const TaskInfo& task,
    const TaskState& state,
    const FrameworkID& frameworkId)
{
  Task t;
  t.mutable_framework_id()->MergeFrom(frameworkId);
  t.set_state(state);
  t.set_name(task.name());
  t.mutable_task_id()->MergeFrom(task.task_id());
  t.mutable_slave_id()->MergeFrom(task.slave_id());
  t.mutable_resources()->MergeFrom(task.resources());

  if (task.has_executor()) {
    t.mutable_executor_id()->CopyFrom(task.executor().executor_id());
  }

  t.mutable_labels()->MergeFrom(task.labels());

  if (task.has_discovery()) {
    t.mutable_discovery()->MergeFrom(task.discovery());
  }

  return t;
}

Option<bool> getTaskHealth(const Task& task)
{
  Option<bool> healthy = None();
  if (task.statuses_size() > 0) {
    // The statuses list only keeps the most recent TaskStatus for
    // each state, and appends later states at the end. Thus the last
    // status is either a terminal state (where health is
    // irrelevant), or the latest RUNNING status.
    TaskStatus lastStatus = task.statuses(task.statuses_size() - 1);
    if (lastStatus.has_healthy()) {
      healthy = lastStatus.healthy();
    }
  }
  return healthy;
}

MasterInfo createMasterInfo(const process::UPID& pid)
{
  MasterInfo info;
  info.set_id(stringify(pid) + "-" + UUID::random().toString());

  // NOTE: Currently, we store the ip in network order, which should
  // be fixed. See MESOS-1201 for more details.
  info.set_ip(pid.address.ip.in().get().s_addr);

  info.set_port(pid.address.port);
  info.set_pid(pid);

  Try<string> hostname = net::getHostname(pid.address.ip);
  if (hostname.isSome()) {
    info.set_hostname(hostname.get());
  }

  return info;
}

} // namespace protobuf {
} // namespace internal {
} // namespace mesos {
<commit_msg>Removed a stale TODO.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <mesos/type_utils.hpp>

#include <process/clock.hpp>
#include <process/pid.hpp>

#include <stout/net.hpp>
#include <stout/stringify.hpp>
#include <stout/uuid.hpp>

#include "messages/messages.hpp"

using std::string;

namespace mesos {
namespace internal {
namespace protobuf {

bool isTerminalState(const TaskState& state)
{
  return (state == TASK_FINISHED ||
          state == TASK_FAILED ||
          state == TASK_KILLED ||
          state == TASK_LOST ||
          state == TASK_ERROR);
}

StatusUpdate createStatusUpdate(
    const FrameworkID& frameworkId,
    const Option<SlaveID>& slaveId,
    const TaskID& taskId,
    const TaskState& state,
    const TaskStatus::Source& source,
    const string& message = "",
    const Option<TaskStatus::Reason>& reason = None(),
    const Option<ExecutorID>& executorId = None(),
    const Option<bool>& healthy = None())
{
  StatusUpdate update;

  update.set_timestamp(process::Clock::now().secs());
  update.set_uuid(UUID::random().toBytes());
  update.mutable_framework_id()->MergeFrom(frameworkId);

  if (slaveId.isSome()) {
    update.mutable_slave_id()->MergeFrom(slaveId.get());
  }

  if (executorId.isSome()) {
    update.mutable_executor_id()->MergeFrom(executorId.get());
  }

  TaskStatus* status = update.mutable_status();
  status->mutable_task_id()->MergeFrom(taskId);

  if (slaveId.isSome()) {
    status->mutable_slave_id()->MergeFrom(slaveId.get());
  }

  status->set_state(state);
  status->set_source(source);
  status->set_message(message);
  status->set_timestamp(update.timestamp());

  if (reason.isSome()) {
    status->set_reason(reason.get());
  }

  if (healthy.isSome()) {
    status->set_healthy(healthy.get());
  }

  return update;
}

Task createTask(
    const TaskInfo& task,
    const TaskState& state,
    const FrameworkID& frameworkId)
{
  Task t;
  t.mutable_framework_id()->MergeFrom(frameworkId);
  t.set_state(state);
  t.set_name(task.name());
  t.mutable_task_id()->MergeFrom(task.task_id());
  t.mutable_slave_id()->MergeFrom(task.slave_id());
  t.mutable_resources()->MergeFrom(task.resources());

  if (task.has_executor()) {
    t.mutable_executor_id()->CopyFrom(task.executor().executor_id());
  }

  t.mutable_labels()->MergeFrom(task.labels());

  if (task.has_discovery()) {
    t.mutable_discovery()->MergeFrom(task.discovery());
  }

  return t;
}

Option<bool> getTaskHealth(const Task& task)
{
  Option<bool> healthy = None();
  if (task.statuses_size() > 0) {
    // The statuses list only keeps the most recent TaskStatus for
    // each state, and appends later states at the end. Thus the last
    // status is either a terminal state (where health is
    // irrelevant), or the latest RUNNING status.
    TaskStatus lastStatus = task.statuses(task.statuses_size() - 1);
    if (lastStatus.has_healthy()) {
      healthy = lastStatus.healthy();
    }
  }
  return healthy;
}

MasterInfo createMasterInfo(const process::UPID& pid)
{
  MasterInfo info;
  info.set_id(stringify(pid) + "-" + UUID::random().toString());

  // NOTE: Currently, we store the ip in network order, which should
  // be fixed. See MESOS-1201 for more details.
  info.set_ip(pid.address.ip.in().get().s_addr);

  info.set_port(pid.address.port);
  info.set_pid(pid);

  Try<string> hostname = net::getHostname(pid.address.ip);
  if (hostname.isSome()) {
    info.set_hostname(hostname.get());
  }

  return info;
}

} // namespace protobuf {
} // namespace internal {
} // namespace mesos {
<|endoftext|>