<commit_before>/*
* 2013+ Copyright (c) Andrey Kashin <kashin.andrej@gmail.com>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/

#ifndef call_tree_hpp
#define call_tree_hpp

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"

#include "actions_set.hpp"

#include <unordered_map>
#include <vector>
#include <mutex>

#include <boost/variant.hpp>
#include <boost/optional.hpp>

namespace react {

typedef boost::variant<
	bool,
	int,
	double,
	std::string
> stat_value_t;

struct JsonRenderer : boost::static_visitor<>
{
	JsonRenderer(const std::string &key, rapidjson::Value &stat_value,
			 rapidjson::Document::AllocatorType &allocator):
		key(key), stat_value(stat_value), allocator(allocator) {}

	void operator () (bool value) const
	{
		stat_value.AddMember(key.c_str(), value, allocator);
	}

	void operator () (int value) const
	{
		stat_value.AddMember(key.c_str(), value, allocator);
	}

	void operator () (double value) const
	{
		stat_value.AddMember(key.c_str(), value, allocator);
	}

	void operator () (const std::string& value) const
	{
		stat_value.AddMember(key.c_str(), value.c_str(), allocator);
	}

private:
	std::string key;
	rapidjson::Value &stat_value;
	rapidjson::Document::AllocatorType &allocator;
};

struct node_t {
	typedef std::vector<std::pair<int, size_t>> Container;

	/*!
	 * \brief Pointer to node type
	 */
	typedef size_t pointer;

	/*!
	 * \brief Initializes node with \a action_code and zero consumed time
	 * \param action_code Action code of the node
	 */
	node_t(int action_code): action_code(action_code), start_time(0), stop_time(0) {}

	/*!
	 * \brief action which this node represents
	 */
	int action_code;

	/*!
	 * \brief time when node action was started
	 */
	int64_t start_time;

	/*!
	 * \brief time when node action was stopped
	 */
	int64_t stop_time;

	/*!
	 * \brief Child nodes, actions that happen inside this action
	 */
	Container links;
};

/*!
 * \brief Stores call tree.
 *
 * Each node of the tree represents information about single action:
 * - Action code
 * - Total time consumed during this action
 */
class call_tree_t {
public:
	typedef node_t::pointer p_node_t;

	/*!
	 * \brief Value for representing null pointer
	 */
	static const p_node_t NO_NODE = -1;

	/*!
	 * \brief Root of the call tree
	 */
	p_node_t root;

	/*!
	 * \brief initializes call tree with single root node and action set
	 * \param actions_set Set of available actions for monitoring in call tree
	 */
	call_tree_t(const actions_set_t &actions_set): actions_set(actions_set) {
		root = new_node(+actions_set_t::NO_ACTION);
	}

	/*!
	 * \brief frees memory consumed by call tree
	 */
	~call_tree_t() {}

	/*!
	 * \brief Returns actions set monitored by this tree
	 * \return Actions set monitored by this tree
	 */
	const actions_set_t& get_actions_set() const {
		return actions_set;
	}

	/*!
	 * \brief Returns links from \a node
	 * \param node Target node
	 * \return Links from target node
	 */
	const node_t::Container &get_node_links(p_node_t node) const {
		return nodes[node].links;
	}

	/*!
	 * \brief Returns an action code for \a node
	 * \param node Target node
	 * \return Action code of the target node
	 */
	int get_node_action_code(p_node_t node) const {
		return nodes[node].action_code;
	}

	/*!
	 * \brief Sets time when action represented by \a node was started
	 * \param node Action's node
	 * \param time Time when action was started
	 */
	void set_node_start_time(p_node_t node, int64_t time) {
		nodes[node].start_time = time;
	}

	/*!
	 * \brief Sets time when action represented by \a node was stopped
	 * \param node Action's node
	 * \param time Time when action was stopped
	 */
	void set_node_stop_time(p_node_t node, int64_t time) {
		nodes[node].stop_time = time;
	}

	/*!
	 * \brief Returns start time of action represented by \a node
	 * \param node Action's node
	 * \return Start time of action
	 */
	int64_t get_node_start_time(p_node_t node) const {
		return nodes[node].start_time;
	}

	/*!
	 * \brief Returns stop time of action represented by \a node
	 * \param node Action's node
	 * \return Stop time of action
	 */
	int64_t get_node_stop_time(p_node_t node) const {
		return nodes[node].stop_time;
	}

	/*!
	 * \brief Adds new child to \a node with \a action_code
	 * \param node Target node
	 * \param action_code Child's action code
	 * \return Pointer to newly created child of \a node with \a action_code
	 */
	p_node_t add_new_link(p_node_t node, int action_code) {
		if (!actions_set.code_is_valid(action_code)) {
			throw std::invalid_argument(
						"Can't add new link: action code is invalid"
						);
		}

		p_node_t action_node = new_node(action_code);
		nodes[node].links.push_back(std::make_pair(action_code, action_node));
		return action_node;
	}

	/*!
	 * \brief Recursively merges this tree into \a rhs_node
	 * \param rhs_node Node in which this tree will be merged
	 * \param rhs_tree Tree in which this tree will be merged
	 */
	void merge_into(call_tree_t::p_node_t rhs_node, call_tree_t& rhs_tree) const {
		merge_into(root, rhs_node, rhs_tree);
	}

	template<typename T>
	void add_stat(const std::string &key, T value) {
		stats[key] = value;
	}

	void add_stat(const std::string &key, const char *value) {
		stats[key] = std::string(value);
	}

	bool has_stat(const std::string &key) const {
		return stats.find(key) != stats.end();
	}

	template<typename T>
	const T &get_stat(const std::string &key) const {
		return boost::get<T>(stats.at(key));
	}

	/*!
	 * \brief Converts call tree to json
	 * \param stat_value Json node for writing
	 * \param allocator Json allocator
	 * \return Modified json node
	 */
	rapidjson::Value& to_json(rapidjson::Value &stat_value,
							  rapidjson::Document::AllocatorType &allocator) const {
		return to_json(root, stat_value, allocator);
	}

private:
	/*!
	 * \internal
	 *
	 * \brief Recursively converts subtree to json
	 * \param current_node Node which subtree will be converted
	 * \param stat_value Json node for writing
	 * \param allocator Json allocator
	 * \return Modified json node
	 */
	rapidjson::Value& to_json(p_node_t current_node, rapidjson::Value &stat_value,
							  rapidjson::Document::AllocatorType &allocator) const {
		if (current_node != root) {
			stat_value.AddMember("name", actions_set.get_action_name(get_node_action_code(current_node)).c_str(), allocator);
			stat_value.AddMember("start_time", (int64_t) get_node_start_time(current_node), allocator);
			stat_value.AddMember("stop_time", (int64_t) get_node_stop_time(current_node), allocator);
		} else {
			for (auto it = stats.begin(); it != stats.end(); ++it) {
				boost::apply_visitor(JsonRenderer(it->first, stat_value, allocator), it->second);
			}
		}

		if (!nodes[current_node].links.empty()) {
			rapidjson::Value subtree_actions(rapidjson::kArrayType);

			for (auto it = nodes[current_node].links.begin(); it != nodes[current_node].links.end(); ++it) {
				p_node_t next_node = it->second;
				rapidjson::Value subtree_value(rapidjson::kObjectType);
				to_json(next_node, subtree_value, allocator);
				subtree_actions.PushBack(subtree_value, allocator);
			}

			stat_value.AddMember("actions", subtree_actions, allocator);
		}

		return stat_value;
	}

	/*!
	 * \internal
	 *
	 * \brief Recursively merges \a lhs_node into \a rhs_node
	 * \param lhs_node Node which will be merged
	 * \param rhs_node Node in which this tree will be merged
	 * \param rhs_tree Tree in which this tree will be merged
	 */
	void merge_into(p_node_t lhs_node, call_tree_t::p_node_t rhs_node, call_tree_t& rhs_tree) const {
		if (lhs_node != root) {
			rhs_tree.set_node_start_time(rhs_node, get_node_start_time(lhs_node));
			rhs_tree.set_node_stop_time(rhs_node, get_node_stop_time(lhs_node));
		}

		for (auto it = nodes[lhs_node].links.begin(); it != nodes[lhs_node].links.end(); ++it) {
			int action_code = it->first;
			p_node_t lhs_next_node = it->second;
			p_node_t rhs_next_node = rhs_tree.add_new_link(rhs_node, action_code);
			merge_into(lhs_next_node, rhs_next_node, rhs_tree);
		}
	}

	/*!
	 * \internal
	 *
	 * \brief Allocates space for new node
	 * \param action_code
	 * \return Pointer to newly created node
	 */
	p_node_t new_node(int action_code) {
		nodes.emplace_back(action_code);
		return nodes.size() - 1;
	}

	/*!
	 * \brief Tree nodes
	 */
	std::vector<node_t> nodes;

	/*!
	 * \brief Available actions for monitoring
	 */
	const actions_set_t &actions_set;

	/*!
	 * \brief Key-Value map for storing arbitary user stats
	 */
	std::unordered_map<std::string, stat_value_t> stats;
};

/*!
 * \brief Concurrent version of time stats tree to handle simultanious updates
 */
class concurrent_call_tree_t {
public:
	/*!
	 * \brief Initializes call_tree with \a actions_set
	 * \param actions_set Set of available action for monitoring
	 */
	concurrent_call_tree_t(actions_set_t &actions_set): call_tree(actions_set) {}

	/*!
	 * \brief Gets ownership of time stats tree
	 */
	void lock() const {
		tree_mutex.lock();
	}

	/*!
	 * \brief Releases ownership of time stats tree
	 */
	void unlock() const {
		tree_mutex.unlock();
	}

	/*!
	 * \brief Returns inner time stats tree
	 * \return Inner time stats tree
	 */
	call_tree_t& get_call_tree() {
		return call_tree;
	}

	/*!
	 * \brief Returns copy of inner time stats tree
	 * \return Copy of inner time stats tree
	 */
	call_tree_t copy_call_tree() const {
		lock();
		call_tree_t call_tree_copy = call_tree;
		unlock();
		return call_tree_copy;
	}

private:
	/*!
	 * \brief Lock to handle concurrency during updates
	 */
	mutable std::mutex tree_mutex;

	/*!
	 * \brief Inner call_tree
	 */
	call_tree_t call_tree;
};

} // namespace react

#endif // call_tree_hpp
<commit_msg>core: call_tree: Docs fixes. Small code refining.<commit_after>/*
* 2013+ Copyright (c) Andrey Kashin <kashin.andrej@gmail.com>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/

#ifndef call_tree_hpp
#define call_tree_hpp

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"

#include "actions_set.hpp"

#include <unordered_map>
#include <vector>
#include <mutex>

#include <boost/variant.hpp>

namespace react {

/*!
 * \brief Types that can be stored in react call tree key-value storage
 */
typedef boost::variant<
	bool,
	int,
	double,
	std::string
> stat_value_t;

/*!
 * \brief Helper structure for printing stats stored in stat_value_t to json
 */
struct JsonRenderer : boost::static_visitor<>
{
	JsonRenderer(const std::string &key, rapidjson::Value &stat_value,
			 rapidjson::Document::AllocatorType &allocator):
		key(key), stat_value(stat_value), allocator(allocator) {}

	void operator () (bool value) const
	{
		stat_value.AddMember(key.c_str(), value, allocator);
	}

	void operator () (int value) const
	{
		stat_value.AddMember(key.c_str(), value, allocator);
	}

	void operator () (double value) const
	{
		stat_value.AddMember(key.c_str(), value, allocator);
	}

	void operator () (const std::string& value) const
	{
		stat_value.AddMember(key.c_str(), value.c_str(), allocator);
	}

private:
	std::string key;
	rapidjson::Value &stat_value;
	rapidjson::Document::AllocatorType &allocator;
};

/*!
 * \brief Represents node of call tree
 */
struct node_t {
	/*!
	 * \brief Type of container where child nodes are stored
	 */
	typedef std::vector<std::pair<int, size_t>> Container;

	/*!
	 * \brief Pointer to node type
	 */
	typedef size_t pointer;

	/*!
	 * \brief Initializes node with \a action_code and zero start and stop times
	 * \param action_code Action code of the node
	 */
	node_t(int action_code): action_code(action_code), start_time(0), stop_time(0) {}

	/*!
	 * \brief Action which this node represents
	 */
	int action_code;

	/*!
	 * \brief Time when node action was started
	 */
	int64_t start_time;

	/*!
	 * \brief Time when node action was stopped
	 */
	int64_t stop_time;

	/*!
	 * \brief Child nodes, actions that happen inside this action
	 */
	Container links;
};

/*!
 * \brief Stores call tree.
 *
 * Each node of the tree represents information about single action:
 * - Action code
 * - Time when action was started
 * - Time when action was stopped
 */
class call_tree_t {
public:
	typedef node_t::pointer p_node_t;

	/*!
	 * \brief Value for representing null node pointer
	 */
	static const p_node_t NO_NODE = -1;

	/*!
	 * \brief Pointer to the root of call tree
	 */
	p_node_t root;

	/*!
	 * \brief Initializes call tree with single root node and specified actions set
	 * \param actions_set Set of available actions for monitoring in call tree
	 */
	call_tree_t(const actions_set_t &actions_set): actions_set(actions_set) {
		root = new_node(+actions_set_t::NO_ACTION);
	}

	/*!
	 * \brief Frees memory consumed by call tree
	 */
	~call_tree_t() {}

	/*!
	 * \brief Returns actions set monitored by this tree
	 * \return Actions set monitored by this tree
	 */
	const actions_set_t& get_actions_set() const {
		return actions_set;
	}

	/*!
	 * \brief Returns links from \a node
	 * \param node Target node
	 * \return Links from target node
	 */
	const node_t::Container &get_node_links(p_node_t node) const {
		return nodes[node].links;
	}

	/*!
	 * \brief Returns an action code for \a node
	 * \param node Target node
	 * \return Action code of the target node
	 */
	int get_node_action_code(p_node_t node) const {
		return nodes[node].action_code;
	}

	/*!
	 * \brief Sets time when action represented by \a node was started
	 * \param node Action's node
	 * \param time Time when action was started
	 */
	void set_node_start_time(p_node_t node, int64_t time) {
		nodes[node].start_time = time;
	}

	/*!
	 * \brief Sets time when action represented by \a node was stopped
	 * \param node Action's node
	 * \param time Time when action was stopped
	 */
	void set_node_stop_time(p_node_t node, int64_t time) {
		nodes[node].stop_time = time;
	}

	/*!
	 * \brief Returns start time of action represented by \a node
	 * \param node Action's node
	 * \return Start time of action
	 */
	int64_t get_node_start_time(p_node_t node) const {
		return nodes[node].start_time;
	}

	/*!
	 * \brief Returns stop time of action represented by \a node
	 * \param node Action's node
	 * \return Stop time of action
	 */
	int64_t get_node_stop_time(p_node_t node) const {
		return nodes[node].stop_time;
	}

	/*!
	 * \brief Adds new child with \a action_code to \a node
	 * \param node Target parent node
	 * \param action_code Child's action code
	 * \return Pointer to newly created child
	 */
	p_node_t add_new_link(p_node_t node, int action_code) {
		if (!actions_set.code_is_valid(action_code)) {
			throw std::invalid_argument("Can't add new link: action code is invalid");
		}

		p_node_t action_node = new_node(action_code);
		nodes[node].links.push_back(std::make_pair(action_code, action_node));
		return action_node;
	}

	template<typename T>
	void add_stat(const std::string &key, T value) {
		stats[key] = value;
	}

	void add_stat(const std::string &key, const char *value) {
		stats[key] = std::string(value);
	}

	bool has_stat(const std::string &key) const {
		return stats.find(key) != stats.end();
	}

	template<typename T>
	const T &get_stat(const std::string &key) const {
		return boost::get<T>(stats.at(key));
	}

	/*!
	 * \brief Converts call tree to json
	 * \param stat_value Json node for writing
	 * \param allocator Json allocator
	 * \return Modified json node
	 */
	rapidjson::Value& to_json(rapidjson::Value &stat_value,
							  rapidjson::Document::AllocatorType &allocator) const {
		return to_json(root, stat_value, allocator);
	}

	/*!
	 * \brief Recursively merges this tree into \a rhs_node
	 * \param rhs_node Node in which this tree will be merged
	 * \param rhs_tree Tree in which this tree will be merged
	 */
	void merge_into(call_tree_t::p_node_t rhs_node, call_tree_t& rhs_tree) const {
		merge_into(root, rhs_node, rhs_tree);
	}

private:
	/*!
	 * \internal
	 *
	 * \brief Recursively converts subtree to json
	 * \param current_node Node which subtree will be converted
	 * \param stat_value Json node for writing
	 * \param allocator Json allocator
	 * \return Modified json node
	 */
	rapidjson::Value& to_json(p_node_t current_node, rapidjson::Value &stat_value,
							  rapidjson::Document::AllocatorType &allocator) const {
		if (current_node != root) {
			stat_value.AddMember("name", actions_set.get_action_name(get_node_action_code(current_node)).c_str(), allocator);
			stat_value.AddMember("start_time", get_node_start_time(current_node), allocator);
			stat_value.AddMember("stop_time", get_node_stop_time(current_node), allocator);
		} else {
			for (auto it = stats.begin(); it != stats.end(); ++it) {
				boost::apply_visitor(JsonRenderer(it->first, stat_value, allocator), it->second);
			}
		}

		if (!nodes[current_node].links.empty()) {
			rapidjson::Value subtree_actions(rapidjson::kArrayType);

			for (auto it = nodes[current_node].links.begin(); it != nodes[current_node].links.end(); ++it) {
				p_node_t next_node = it->second;
				rapidjson::Value subtree_value(rapidjson::kObjectType);
				to_json(next_node, subtree_value, allocator);
				subtree_actions.PushBack(subtree_value, allocator);
			}

			stat_value.AddMember("actions", subtree_actions, allocator);
		}

		return stat_value;
	}

	/*!
	 * \internal
	 *
	 * \brief Recursively merges \a lhs_node into \a rhs_node
	 * \param lhs_node Node which will be merged
	 * \param rhs_node Node in which this tree will be merged
	 * \param rhs_tree Tree in which this tree will be merged
	 */
	void merge_into(p_node_t lhs_node, call_tree_t::p_node_t rhs_node, call_tree_t& rhs_tree) const {
		if (lhs_node != root) {
			rhs_tree.set_node_start_time(rhs_node, get_node_start_time(lhs_node));
			rhs_tree.set_node_stop_time(rhs_node, get_node_stop_time(lhs_node));
		}

		for (auto it = nodes[lhs_node].links.begin(); it != nodes[lhs_node].links.end(); ++it) {
			int action_code = it->first;
			p_node_t lhs_next_node = it->second;
			p_node_t rhs_next_node = rhs_tree.add_new_link(rhs_node, action_code);
			merge_into(lhs_next_node, rhs_next_node, rhs_tree);
		}
	}

	/*!
	 * \internal
	 *
	 * \brief Allocates space for new node
	 * \param action_code Action code of new node
	 * \return Pointer to newly created node
	 */
	p_node_t new_node(int action_code) {
		nodes.emplace_back(action_code);
		return nodes.size() - 1;
	}

	/*!
	 * \brief Tree nodes
	 */
	std::vector<node_t> nodes;

	/*!
	 * \brief Available actions for monitoring
	 */
	const actions_set_t &actions_set;

	/*!
	 * \brief Key-Value map for storing arbitary user stats
	 */
	std::unordered_map<std::string, stat_value_t> stats;
};

/*!
 * \brief Concurrent version of time stats tree to handle simultanious updates
 */
class concurrent_call_tree_t {
public:
	/*!
	 * \brief Initializes call_tree with \a actions_set
	 * \param actions_set Set of available action for monitoring
	 */
	concurrent_call_tree_t(actions_set_t &actions_set): call_tree(actions_set) {}

	/*!
	 * \brief Gets ownership of time stats tree
	 */
	void lock() const {
		tree_mutex.lock();
	}

	/*!
	 * \brief Releases ownership of time stats tree
	 */
	void unlock() const {
		tree_mutex.unlock();
	}

	/*!
	 * \brief Returns inner time stats tree
	 * \return Inner time stats tree
	 */
	call_tree_t& get_call_tree() {
		return call_tree;
	}

	/*!
	 * \brief Returns copy of inner time stats tree
	 * \return Copy of inner time stats tree
	 */
	call_tree_t copy_call_tree() const {
		lock();
		call_tree_t call_tree_copy = call_tree;
		unlock();
		return call_tree_copy;
	}

private:
	/*!
	 * \brief Lock to handle concurrency during updates
	 */
	mutable std::mutex tree_mutex;

	/*!
	 * \brief Inner call_tree
	 */
	call_tree_t call_tree;
};

} // namespace react

#endif // call_tree_hpp
<|endoftext|>


<commit_before>#ifndef SIMDIFY_SIMDIFY_HPP
#define SIMDIFY_SIMDIFY_HPP
#define SIMDIFY

//
// C++, C++11 checks
//
#ifndef __cplusplus
#error "Simdify requires C++."
#endif

#if defined(_MSC_VER) && _MSC_VER < 1900
#error "Simdify requires Visual Studio 2015."
#endif

#if !defined(_MSC_VER) && __cplusplus < 201103L && !defined(__GXX_EXPERIMENTAL_CXX0X__)
#error "Simdify requires C++11. Please use the setting '-std=c++0x' or '-std=c++11'."
#endif

//
// defaults for feature requests
//
#ifndef SIMDIFY_NEED_INT
#define SIMDIFY_NEED_INT 1 // require integer operations for SIMD types
#endif
#ifndef SIMDIFY_NEED_AVX
#define SIMDIFY_NEED_AVX 0 // require AVX SIMD types to be declared
#endif
#ifndef SIMDIFY_NEED_SSE
#define SIMDIFY_NEED_SSE 0 // require SSE SIMD types to be declared
#endif
#ifndef SIMDIFY_NEED_DUM
#define SIMDIFY_NEED_DUM 0 // require dummy SIMD types to be declared
#endif

//
// fix MSVC borked SSE macros (ICC has got them right though)
//
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)

#if defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)
#define __SSE__
#endif

#if defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
#define __SSE2__
#endif

#if defined(__AVX__)
#define __SSE3__
#define __SSSE3__
#define __SSE4_1__
#define __SSE4_2__
#endif // __AVX__

#endif // _MSC_VER

//
// include all supported SIMD types
// use the SIMDIFY_NEED_* macros to force the include
//
#if SIMDIFY_NEED_AVX || \
    (!SIMDIFY_NEED_INT && defined(__AVX__)) || \
    (SIMDIFY_NEED_INT && defined(__AVX2__))
#include "simd_types/avx.hpp"
#endif

#if SIMDIFY_NEED_SSE || defined(__SSE2__)
#include "simd_types/sse.hpp"
#endif

#include "simd_types/dum.hpp"

//
// set some (successfully loaded) SIMD type as simd_t
// use SIMDIFY_PREFER_* to use a specific type
//
namespace simd {
#if defined(SIMDIFY_PREFER_AVX) && defined(SIMDIFY_HAVE_AVX)
    using vecf = avxf;
    using vecu = avxu;
    using vecs = avxs;
#elif defined(SIMDIFY_PREFER_SSE) && defined(SIMDIFY_HAVE_SSE)
    using vecf = ssef;
    using vecu = sseu;
    using vecs = sses;
#elif defined(SIMDIFY_PREFER_DUM) && defined(SIMDIFY_HAVE_DUM)
    using vecf = dumf;
    using vecu = dumu;
    using vecs = dums;
#elif defined(SIMDIFY_HAVE_AVX)
    using vecf = avxf;
    using vecu = avxu;
    using vecs = avxs;
#elif defined(SIMDIFY_HAVE_SSE)
    using vecf = ssef;
    using vecu = sseu;
    using vecs = sses;
#elif defined(SIMDIFY_HAVE_DUM)
    using vecf = dumf;
    using vecu = dumu;
    using vecs = dums;
#else
#error "Simdify could not determine a suitable SIMD type as simd_t."
#endif

}

#endif // SIMDIFY_SIMDIFY_HPP
<commit_msg>Report library version via macros<commit_after>#ifndef SIMDIFY_SIMDIFY_HPP
#define SIMDIFY_SIMDIFY_HPP
#define SIMDIFY
#define SIMDIFY_MAJOR 0
#define SIMDIFY_MINOR 1
#define SIMDIFY_PATCHLEVEL 0

//
// C++, C++11 checks
//
#ifndef __cplusplus
#error "Simdify requires C++."
#endif

#if defined(_MSC_VER) && _MSC_VER < 1900
#error "Simdify requires Visual Studio 2015."
#endif

#if !defined(_MSC_VER) && __cplusplus < 201103L && !defined(__GXX_EXPERIMENTAL_CXX0X__)
#error "Simdify requires C++11. Please use the setting '-std=c++0x' or '-std=c++11'."
#endif

//
// defaults for feature requests
//
#ifndef SIMDIFY_NEED_INT
#define SIMDIFY_NEED_INT 1 // require integer operations for SIMD types
#endif
#ifndef SIMDIFY_NEED_AVX
#define SIMDIFY_NEED_AVX 0 // require AVX SIMD types to be declared
#endif
#ifndef SIMDIFY_NEED_SSE
#define SIMDIFY_NEED_SSE 0 // require SSE SIMD types to be declared
#endif
#ifndef SIMDIFY_NEED_DUM
#define SIMDIFY_NEED_DUM 0 // require dummy SIMD types to be declared
#endif

//
// fix MSVC borked SSE macros (ICC has got them right though)
//
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)

#if defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)
#define __SSE__
#endif

#if defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
#define __SSE2__
#endif

#if defined(__AVX__)
#define __SSE3__
#define __SSSE3__
#define __SSE4_1__
#define __SSE4_2__
#endif // __AVX__

#endif // _MSC_VER

//
// include all supported SIMD types
// use the SIMDIFY_NEED_* macros to force the include
//
#if SIMDIFY_NEED_AVX || \
    (!SIMDIFY_NEED_INT && defined(__AVX__)) || \
    (SIMDIFY_NEED_INT && defined(__AVX2__))
#include "simd_types/avx.hpp"
#endif

#if SIMDIFY_NEED_SSE || defined(__SSE2__)
#include "simd_types/sse.hpp"
#endif

#include "simd_types/dum.hpp"

//
// set some (successfully loaded) SIMD type as simd_t
// use SIMDIFY_PREFER_* to use a specific type
//
namespace simd {
#if defined(SIMDIFY_PREFER_AVX) && defined(SIMDIFY_HAVE_AVX)
    using vecf = avxf;
    using vecu = avxu;
    using vecs = avxs;
#elif defined(SIMDIFY_PREFER_SSE) && defined(SIMDIFY_HAVE_SSE)
    using vecf = ssef;
    using vecu = sseu;
    using vecs = sses;
#elif defined(SIMDIFY_PREFER_DUM) && defined(SIMDIFY_HAVE_DUM)
    using vecf = dumf;
    using vecu = dumu;
    using vecs = dums;
#elif defined(SIMDIFY_HAVE_AVX)
    using vecf = avxf;
    using vecu = avxu;
    using vecs = avxs;
#elif defined(SIMDIFY_HAVE_SSE)
    using vecf = ssef;
    using vecu = sseu;
    using vecs = sses;
#elif defined(SIMDIFY_HAVE_DUM)
    using vecf = dumf;
    using vecu = dumu;
    using vecs = dums;
#else
#error "Simdify could not determine a suitable SIMD type as simd_t."
#endif

}

#endif // SIMDIFY_SIMDIFY_HPP
<|endoftext|>


<commit_before>// Copyright 2015-2020 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_XCODE_PROJECT_HPP
#define OUZEL_XCODE_PROJECT_HPP

#include <fstream>
#include "OuzelProject.hpp"
#include "PBXBuildFile.hpp"
#include "PBXContainerItemProxy.hpp"
#include "PBXFileReference.hpp"
#include "PBXFrameworksBuildPhase.hpp"
#include "PBXGroup.hpp"
#include "PBXNativeTarget.hpp"
#include "PBXProject.hpp"
#include "PBXReferenceProxy.hpp"
#include "PBXResourcesBuildPhase.hpp"
#include "PBXShellScriptBuildPhase.hpp"
#include "PBXSourcesBuildPhase.hpp"
#include "PBXTargetDependency.hpp"
#include "XCBuildConfiguration.hpp"
#include "XCConfigurationList.hpp"
#include "storage/FileSystem.hpp"
#include "utils/Plist.hpp"

namespace ouzel
{
    namespace xcode
    {
        class Project final
        {
        public:
            Project(const OuzelProject& p):
                project(p)
            {
            }

            void generate()
            {
                const storage::Path projectFilename = project.getPath().getFilename();
                const storage::Path projectDirectory = project.getPath().getDirectory();

                auto xcodeProjectDirectory = projectDirectory / storage::Path{project.getName() + ".xcodeproj"};
                auto xcodeProjectDirectoryType = xcodeProjectDirectory.getType();

                if (xcodeProjectDirectoryType == storage::Path::Type::NotFound)
                    storage::FileSystem::createDirectory(xcodeProjectDirectory);
                else if (xcodeProjectDirectoryType != storage::Path::Type::Directory)
                {
                    storage::FileSystem::deleteFile(xcodeProjectDirectory);
                    storage::FileSystem::createDirectory(xcodeProjectDirectory);
                }

                auto pbxProjectFile = xcodeProjectDirectory / storage::Path{"project.pbxproj"};

                constexpr auto libouzelIosId = Id{0x30, 0x3B, 0x75, 0x33, 0x1C, 0x2A, 0x3C, 0x58, 0x00, 0xFE, 0xDE, 0x92};
                constexpr auto libouzelMacOsId = Id{0x30, 0xA3, 0x96, 0x29, 0x24, 0x37, 0x73, 0xB5, 0x00, 0xD8, 0xE2, 0x8E};
                constexpr auto libouzelTvosId = Id{0x30, 0xA3, 0x96, 0x29, 0x24, 0x37, 0x73, 0xB5, 0x00, 0xD8, 0xE2, 0x8E};
                constexpr auto ouzelId = Id{0x30, 0xA3, 0x96, 0x29, 0x24, 0x37, 0x73, 0xB5, 0x00, 0xD8, 0xE2, 0x8E};

                std::vector<PBXFileReferenceRef> frameworkFileReferences;
                std::vector<PBXFileElementRef> frameworkFiles;

                const auto frameworksPath = storage::Path{"System/Library/Frameworks"};
                for (const auto& framework : {
                    "AudioToolbox.framework",
                    "AudioUnit.framework",
                    "Cocoa.framework",
                    "CoreAudio.framework",
                    "CoreVideo.framework",
                    "GameController.framework",
                    "IOKit.framework",
                    "Metal.framework",
                    "OpenAL.framework",
                    "OpenGL.framework",
                    "QuartzCore.framework"
                })
                {
                    const auto& frameworkFileReference = create<PBXFileReference>(framework,
                                                                                frameworksPath / framework,
                                                                                PBXFileType::WrapperFramework,
                                                                                PBXSourceTree::SdkRoot);

                    frameworkFileReferences.push_back(frameworkFileReference);
                    frameworkFiles.push_back(frameworkFileReference);
                }

                const auto ouzelProjectPath = project.getOuzelPath() / "build" / "ouzel.xcodeproj";
                const auto& ouzelProjectFileRef = create<PBXFileReference>("ouzel.xcodeproj", ouzelProjectPath,
                                                                           PBXFileType::WrapperPBProject,
                                                                           PBXSourceTree::Group);
                const auto& libouzelIosProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                             PBXContainerItemProxy::Reference,
                                                                             libouzelIosId, "libouzel_ios");

                const auto& libouzelIosReferenceProxy = create<PBXReferenceProxy>("", "libouzel_ios.a",
                                                                                PBXFileType::ArchiveAr,
                                                                                PBXSourceTree::BuildProductsDir,
                                                                                libouzelIosProxy);

                const auto& libouzelMacOsProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                               PBXContainerItemProxy::Reference,
                                                                               libouzelMacOsId, "libouzel_macos");

                const auto& libouzelMacOsReferenceProxy = create<PBXReferenceProxy>("", "libouzel_macos.a",
                                                                                PBXFileType::ArchiveAr,
                                                                                PBXSourceTree::BuildProductsDir,
                                                                                libouzelMacOsProxy);

                const auto& libouzelTvosProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                              PBXContainerItemProxy::Reference,
                                                                              libouzelTvosId, "libouzel_tvos");

                const auto& libouzelTvosReferenceProxy = create<PBXReferenceProxy>("", "libouzel_tvos.a",
                                                                                PBXFileType::ArchiveAr,
                                                                                PBXSourceTree::BuildProductsDir,
                                                                                libouzelTvosProxy);

                const auto& ouzelProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                       PBXContainerItemProxy::Reference,
                                                                       ouzelId, "ouzel");

                const auto& ouzelNativeTargetProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                                PBXContainerItemProxy::NativeTarget,
                                                                                ouzelId, "ouzel");

                const auto& ouzelReferenceProxy = create<PBXReferenceProxy>("", "ouzel",
                                                                            PBXFileType::CompiledMachOExecutable,
                                                                            PBXSourceTree::BuildProductsDir,
                                                                            ouzelProxy);

                const auto& frameworksGroup = create<PBXGroup>("Frameworks", storage::Path{},
                                                               frameworkFiles,
                                                               PBXSourceTree::Group);

                const auto& ouzelPoductRefGroup = create<PBXGroup>("Products", storage::Path{},
                                                                   std::vector<PBXFileElementRef>{
                                                                       libouzelIosReferenceProxy,
                                                                       libouzelMacOsReferenceProxy,
                                                                       libouzelTvosReferenceProxy,
                                                                       ouzelReferenceProxy},
                                                                   PBXSourceTree::Group);

                const auto& productFile = create<PBXFileReference>("", storage::Path{project.getName() + ".app"},
                                                                   PBXFileType::WrapperApplication,
                                                                   PBXSourceTree::BuildProductsDir);

                const auto& resourcesGroup = create<PBXGroup>("", storage::Path{"Resources"},
                                                              std::vector<PBXFileElementRef>{},
                                                              PBXSourceTree::Group);

                const auto& productRefGroup = create<PBXGroup>("Products", storage::Path{},
                                                               std::vector<PBXFileElementRef>{productFile},
                                                               PBXSourceTree::Group);

                std::vector<PBXBuildFileRef> buildFiles;
                std::vector<PBXFileElementRef> sourceFiles;

                for (const auto& sourceFile : project.getSourceFiles())
                {
                    const auto extension = sourceFile.getExtension();
                    // TODO: support more file formats
                    const auto fileType = extension == "plist" ? PBXFileType::TextPlistXml :
                        extension == "c" ? PBXFileType::SourcecodeC :
                        extension == "h" ? PBXFileType::SourcecodeCH :
                        extension == "cpp" ? PBXFileType::SourcecodeCppCpp :
                        extension == "hpp" ? PBXFileType::SourcecodeCppH :
                        throw std::runtime_error("Unsupported file type");

                    const auto& fileReference = create<PBXFileReference>("", sourceFile, fileType, PBXSourceTree::Group);
                    sourceFiles.push_back(fileReference);

                    const auto& buildFile = create<PBXBuildFile>(fileReference);
                    buildFiles.push_back(buildFile);
                }

                const auto& sourceGroup = create<PBXGroup>("src", storage::Path{"src"},
                                                           sourceFiles, PBXSourceTree::Group);

                const auto& mainGroup = create<PBXGroup>("", storage::Path{},
                                                         std::vector<PBXFileElementRef>{
                                                             frameworksGroup,
                                                             ouzelProjectFileRef,
                                                             productRefGroup,
                                                             resourcesGroup,
                                                             sourceGroup},
                                                         PBXSourceTree::Group);

                const auto headerSearchPath = std::string(project.getOuzelPath() / "engine");
                const auto& debugConfiguration = create<XCBuildConfiguration>("Debug",
                                                                              std::map<std::string, std::string>{
                                                                                {"CLANG_CXX_LANGUAGE_STANDARD", "c++14"},
                                                                                {"GCC_OPTIMIZATION_LEVEL", "0"},
                                                                                {"HEADER_SEARCH_PATHS", headerSearchPath}});

                const auto& releaseConfiguration = create<XCBuildConfiguration>("Release",
                                                                                std::map<std::string, std::string>{
                                                                                {"CLANG_CXX_LANGUAGE_STANDARD", "c++14"},
                                                                                {"HEADER_SEARCH_PATHS", headerSearchPath}});

                const auto& projectConfigurationList = create<XCConfigurationList>(std::vector<XCBuildConfigurationRef>{
                                                                                debugConfiguration,
                                                                                releaseConfiguration},
                                                                                releaseConfiguration.getName());

                std::vector<PBXTargetRef> targets;

                for (const auto platform : project.getPlatforms())
                {
                    // TODO: do it for all platforms
                    if (platform == Platform::MacOs)
                    {
                        const auto& targetDebugConfiguration = create<XCBuildConfiguration>("Debug",
                                                                                std::map<std::string, std::string>{
                                                                                {"PRODUCT_NAME", project.getName()}});

                        const auto& targetReleaseConfiguration = create<XCBuildConfiguration>("Release",
                                                                                std::map<std::string, std::string>{
                                                                                {"PRODUCT_NAME", project.getName()}});

                        const auto& targetConfigurationList = create<XCConfigurationList>(std::vector<XCBuildConfigurationRef>{
                                                                                targetDebugConfiguration,
                                                                                targetReleaseConfiguration},
                                                                                targetReleaseConfiguration.getName());

                        const auto& sourcesBuildPhase = create<PBXSourcesBuildPhase>(buildFiles);

                        std::vector<PBXBuildFileRef> frameworkBuildFiles;
                        for (const PBXFileReferenceRef& frameworkFileReference : frameworkFileReferences)
                        {
                            const auto& frameworkBuildFile = create<PBXBuildFile>(frameworkFileReference);
                            frameworkBuildFiles.push_back(frameworkBuildFile);
                        }

                        const auto& libouzelMacOsBuildFile = create<PBXBuildFile>(libouzelMacOsReferenceProxy);
                        frameworkBuildFiles.push_back(libouzelMacOsBuildFile);

                        const auto& frameworksBuildPhase = create<PBXFrameworksBuildPhase>(frameworkBuildFiles);

                        // TODO: implement asset build shell script
                        const auto& assetsBuildPhase = create<PBXShellScriptBuildPhase>("$BUILT_PRODUCTS_DIR/ouzel --export-assets $PROJECT_DIR/" + std::string(projectFilename));

                        // TODO: implement resource copy
                        const auto& resourcesBuildPhase = create<PBXResourcesBuildPhase>(std::vector<PBXBuildFileRef>{});

                        const auto& ouzelDependency = create<PBXTargetDependency>("ouzel", ouzelNativeTargetProxy);

                        const auto& nativeTarget = create<PBXNativeTarget>(project.getName() + " macOS",
                                                                           targetConfigurationList,
                                                                           std::vector<PBXBuildPhaseRef>{sourcesBuildPhase, frameworksBuildPhase, assetsBuildPhase, resourcesBuildPhase},
                                                                           std::vector<PBXTargetDependencyRef>{ouzelDependency},
                                                                           productFile);
                        targets.push_back(nativeTarget);
                    }
                }

                const auto& pbxProject = create<PBXProject>(project.getOrganization(),
                                                            projectConfigurationList,
                                                            mainGroup,
                                                            productRefGroup,
                                                            std::map<std::string, PBXObjectRef>{
                                                                {"ProductGroup", ouzelPoductRefGroup},
                                                                {"ProjectRef", ouzelProjectFileRef}},
                                                            targets);

                rootObject = &pbxProject;

                std::ofstream file(pbxProjectFile, std::ios::trunc);
                file << plist::encode(encode());
            }

        private:
            template <class T, class ...Args>
            T& create(Args&& ...args)
            {
                std::unique_ptr<T> object = std::make_unique<T>(std::forward<Args>(args)...);
                T& result = *object;
                objects.push_back(std::move(object));
                return result;
            }

            plist::Value encode() const {
                plist::Value result = plist::Value::Dictionary{
                    {"archiveVersion", 1},
                    {"classes", plist::Value::Dictionary{}},
                    {"objectVersion", 50},
                    {"objects", plist::Value::Dictionary{}},
                    {"rootObject", rootObject ? toString(rootObject->getId()): ""}
                };

                for (const auto& object : objects)
                    result["objects"][toString(object->getId())] = object->encode();

                return result;
            }

            const OuzelProject& project;
            std::vector<std::unique_ptr<PBXObject>> objects;
            const PBXObject* rootObject;
        };
    }
}

#endif // OUZEL_XCODE_PROJECT_HPP
<commit_msg>Move frameworks to platfomr code<commit_after>// Copyright 2015-2020 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_XCODE_PROJECT_HPP
#define OUZEL_XCODE_PROJECT_HPP

#include <fstream>
#include "OuzelProject.hpp"
#include "PBXBuildFile.hpp"
#include "PBXContainerItemProxy.hpp"
#include "PBXFileReference.hpp"
#include "PBXFrameworksBuildPhase.hpp"
#include "PBXGroup.hpp"
#include "PBXNativeTarget.hpp"
#include "PBXProject.hpp"
#include "PBXReferenceProxy.hpp"
#include "PBXResourcesBuildPhase.hpp"
#include "PBXShellScriptBuildPhase.hpp"
#include "PBXSourcesBuildPhase.hpp"
#include "PBXTargetDependency.hpp"
#include "XCBuildConfiguration.hpp"
#include "XCConfigurationList.hpp"
#include "storage/FileSystem.hpp"
#include "utils/Plist.hpp"

namespace ouzel
{
    namespace xcode
    {
        class Project final
        {
        public:
            Project(const OuzelProject& p):
                project(p)
            {
            }

            void generate()
            {
                const storage::Path projectFilename = project.getPath().getFilename();
                const storage::Path projectDirectory = project.getPath().getDirectory();

                auto xcodeProjectDirectory = projectDirectory / storage::Path{project.getName() + ".xcodeproj"};
                auto xcodeProjectDirectoryType = xcodeProjectDirectory.getType();

                if (xcodeProjectDirectoryType == storage::Path::Type::NotFound)
                    storage::FileSystem::createDirectory(xcodeProjectDirectory);
                else if (xcodeProjectDirectoryType != storage::Path::Type::Directory)
                {
                    storage::FileSystem::deleteFile(xcodeProjectDirectory);
                    storage::FileSystem::createDirectory(xcodeProjectDirectory);
                }

                auto pbxProjectFile = xcodeProjectDirectory / storage::Path{"project.pbxproj"};

                constexpr auto libouzelIosId = Id{0x30, 0x3B, 0x75, 0x33, 0x1C, 0x2A, 0x3C, 0x58, 0x00, 0xFE, 0xDE, 0x92};
                constexpr auto libouzelMacOsId = Id{0x30, 0xA3, 0x96, 0x29, 0x24, 0x37, 0x73, 0xB5, 0x00, 0xD8, 0xE2, 0x8E};
                constexpr auto libouzelTvosId = Id{0x30, 0xA3, 0x96, 0x29, 0x24, 0x37, 0x73, 0xB5, 0x00, 0xD8, 0xE2, 0x8E};
                constexpr auto ouzelId = Id{0x30, 0xA3, 0x96, 0x29, 0x24, 0x37, 0x73, 0xB5, 0x00, 0xD8, 0xE2, 0x8E};

                const auto ouzelProjectPath = project.getOuzelPath() / "build" / "ouzel.xcodeproj";
                const auto& ouzelProjectFileRef = create<PBXFileReference>("ouzel.xcodeproj", ouzelProjectPath,
                                                                           PBXFileType::WrapperPBProject,
                                                                           PBXSourceTree::Group);
                const auto& libouzelIosProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                             PBXContainerItemProxy::Reference,
                                                                             libouzelIosId, "libouzel_ios");

                const auto& libouzelIosReferenceProxy = create<PBXReferenceProxy>("", "libouzel_ios.a",
                                                                                PBXFileType::ArchiveAr,
                                                                                PBXSourceTree::BuildProductsDir,
                                                                                libouzelIosProxy);

                const auto& libouzelMacOsProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                               PBXContainerItemProxy::Reference,
                                                                               libouzelMacOsId, "libouzel_macos");

                const auto& libouzelMacOsReferenceProxy = create<PBXReferenceProxy>("", "libouzel_macos.a",
                                                                                PBXFileType::ArchiveAr,
                                                                                PBXSourceTree::BuildProductsDir,
                                                                                libouzelMacOsProxy);

                const auto& libouzelTvosProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                              PBXContainerItemProxy::Reference,
                                                                              libouzelTvosId, "libouzel_tvos");

                const auto& libouzelTvosReferenceProxy = create<PBXReferenceProxy>("", "libouzel_tvos.a",
                                                                                PBXFileType::ArchiveAr,
                                                                                PBXSourceTree::BuildProductsDir,
                                                                                libouzelTvosProxy);

                const auto& ouzelProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                       PBXContainerItemProxy::Reference,
                                                                       ouzelId, "ouzel");

                const auto& ouzelNativeTargetProxy = create<PBXContainerItemProxy>(ouzelProjectFileRef,
                                                                                PBXContainerItemProxy::NativeTarget,
                                                                                ouzelId, "ouzel");

                const auto& ouzelReferenceProxy = create<PBXReferenceProxy>("", "ouzel",
                                                                            PBXFileType::CompiledMachOExecutable,
                                                                            PBXSourceTree::BuildProductsDir,
                                                                            ouzelProxy);

                const auto& ouzelPoductRefGroup = create<PBXGroup>("Products", storage::Path{},
                                                                   std::vector<PBXFileElementRef>{
                                                                       libouzelIosReferenceProxy,
                                                                       libouzelMacOsReferenceProxy,
                                                                       libouzelTvosReferenceProxy,
                                                                       ouzelReferenceProxy},
                                                                   PBXSourceTree::Group);

                const auto& productFile = create<PBXFileReference>("", storage::Path{project.getName() + ".app"},
                                                                   PBXFileType::WrapperApplication,
                                                                   PBXSourceTree::BuildProductsDir);

                const auto& resourcesGroup = create<PBXGroup>("", storage::Path{"Resources"},
                                                              std::vector<PBXFileElementRef>{},
                                                              PBXSourceTree::Group);

                const auto& productRefGroup = create<PBXGroup>("Products", storage::Path{},
                                                               std::vector<PBXFileElementRef>{productFile},
                                                               PBXSourceTree::Group);

                std::vector<PBXBuildFileRef> buildFiles;
                std::vector<PBXFileElementRef> sourceFiles;

                for (const auto& sourceFile : project.getSourceFiles())
                {
                    const auto extension = sourceFile.getExtension();
                    // TODO: support more file formats
                    const auto fileType = extension == "plist" ? PBXFileType::TextPlistXml :
                        extension == "c" ? PBXFileType::SourcecodeC :
                        extension == "h" ? PBXFileType::SourcecodeCH :
                        extension == "cpp" ? PBXFileType::SourcecodeCppCpp :
                        extension == "hpp" ? PBXFileType::SourcecodeCppH :
                        throw std::runtime_error("Unsupported file type");

                    const auto& fileReference = create<PBXFileReference>("", sourceFile, fileType, PBXSourceTree::Group);
                    sourceFiles.push_back(fileReference);

                    const auto& buildFile = create<PBXBuildFile>(fileReference);
                    buildFiles.push_back(buildFile);
                }

                const auto& sourceGroup = create<PBXGroup>("src", storage::Path{"src"},
                                                           sourceFiles, PBXSourceTree::Group);

                const auto headerSearchPath = std::string(project.getOuzelPath() / "engine");
                const auto& debugConfiguration = create<XCBuildConfiguration>("Debug",
                                                                              std::map<std::string, std::string>{
                                                                                {"CLANG_CXX_LANGUAGE_STANDARD", "c++14"},
                                                                                {"GCC_OPTIMIZATION_LEVEL", "0"},
                                                                                {"HEADER_SEARCH_PATHS", headerSearchPath}});

                const auto& releaseConfiguration = create<XCBuildConfiguration>("Release",
                                                                                std::map<std::string, std::string>{
                                                                                {"CLANG_CXX_LANGUAGE_STANDARD", "c++14"},
                                                                                {"HEADER_SEARCH_PATHS", headerSearchPath}});

                const auto& projectConfigurationList = create<XCConfigurationList>(std::vector<XCBuildConfigurationRef>{
                                                                                debugConfiguration,
                                                                                releaseConfiguration},
                                                                                releaseConfiguration.getName());

                std::vector<PBXTargetRef> targets;
                std::vector<PBXFileElementRef> frameworkFiles;

                for (const auto platform : project.getPlatforms())
                {
                    // TODO: do it for all platforms
                    if (platform == Platform::MacOs)
                    {
                        const auto& targetDebugConfiguration = create<XCBuildConfiguration>("Debug",
                                                                                std::map<std::string, std::string>{
                                                                                {"PRODUCT_NAME", project.getName()}});

                        const auto& targetReleaseConfiguration = create<XCBuildConfiguration>("Release",
                                                                                std::map<std::string, std::string>{
                                                                                {"PRODUCT_NAME", project.getName()}});

                        const auto& targetConfigurationList = create<XCConfigurationList>(std::vector<XCBuildConfigurationRef>{
                                                                                targetDebugConfiguration,
                                                                                targetReleaseConfiguration},
                                                                                targetReleaseConfiguration.getName());

                        const auto& sourcesBuildPhase = create<PBXSourcesBuildPhase>(buildFiles);

                        std::vector<PBXFileReferenceRef> frameworkFileReferences;

                        const auto frameworksPath = storage::Path{"System/Library/Frameworks"};
                        for (const auto& framework : {
                            "AudioToolbox.framework",
                            "AudioUnit.framework",
                            "Cocoa.framework",
                            "CoreAudio.framework",
                            "CoreVideo.framework",
                            "GameController.framework",
                            "IOKit.framework",
                            "Metal.framework",
                            "OpenAL.framework",
                            "OpenGL.framework",
                            "QuartzCore.framework"
                        })
                        {
                            const auto& frameworkFileReference = create<PBXFileReference>(framework,
                                                                                frameworksPath / framework,
                                                                                PBXFileType::WrapperFramework,
                                                                                PBXSourceTree::SdkRoot);

                            frameworkFileReferences.push_back(frameworkFileReference);
                            frameworkFiles.push_back(frameworkFileReference);
                        }

                        std::vector<PBXBuildFileRef> frameworkBuildFiles;
                        for (const PBXFileReferenceRef& frameworkFileReference : frameworkFileReferences)
                        {
                            const auto& frameworkBuildFile = create<PBXBuildFile>(frameworkFileReference);
                            frameworkBuildFiles.push_back(frameworkBuildFile);
                        }

                        const auto& libouzelMacOsBuildFile = create<PBXBuildFile>(libouzelMacOsReferenceProxy);
                        frameworkBuildFiles.push_back(libouzelMacOsBuildFile);

                        const auto& frameworksBuildPhase = create<PBXFrameworksBuildPhase>(frameworkBuildFiles);

                        // TODO: implement asset build shell script
                        const auto& assetsBuildPhase = create<PBXShellScriptBuildPhase>("$BUILT_PRODUCTS_DIR/ouzel --export-assets $PROJECT_DIR/" + std::string(projectFilename));

                        // TODO: implement resource copy
                        const auto& resourcesBuildPhase = create<PBXResourcesBuildPhase>(std::vector<PBXBuildFileRef>{});

                        const auto& ouzelDependency = create<PBXTargetDependency>("ouzel", ouzelNativeTargetProxy);

                        const auto& nativeTarget = create<PBXNativeTarget>(project.getName() + " macOS",
                                                                           targetConfigurationList,
                                                                           std::vector<PBXBuildPhaseRef>{sourcesBuildPhase, frameworksBuildPhase, assetsBuildPhase, resourcesBuildPhase},
                                                                           std::vector<PBXTargetDependencyRef>{ouzelDependency},
                                                                           productFile);
                        targets.push_back(nativeTarget);
                    }
                }

                const auto& frameworksGroup = create<PBXGroup>("Frameworks", storage::Path{},
                                                               frameworkFiles,
                                                               PBXSourceTree::Group);

                const auto& mainGroup = create<PBXGroup>("", storage::Path{},
                                                         std::vector<PBXFileElementRef>{
                                                             frameworksGroup,
                                                             ouzelProjectFileRef,
                                                             productRefGroup,
                                                             resourcesGroup,
                                                             sourceGroup},
                                                         PBXSourceTree::Group);

                const auto& pbxProject = create<PBXProject>(project.getOrganization(),
                                                            projectConfigurationList,
                                                            mainGroup,
                                                            productRefGroup,
                                                            std::map<std::string, PBXObjectRef>{
                                                                {"ProductGroup", ouzelPoductRefGroup},
                                                                {"ProjectRef", ouzelProjectFileRef}},
                                                            targets);

                rootObject = &pbxProject;

                std::ofstream file(pbxProjectFile, std::ios::trunc);
                file << plist::encode(encode());
            }

        private:
            template <class T, class ...Args>
            T& create(Args&& ...args)
            {
                std::unique_ptr<T> object = std::make_unique<T>(std::forward<Args>(args)...);
                T& result = *object;
                objects.push_back(std::move(object));
                return result;
            }

            plist::Value encode() const {
                plist::Value result = plist::Value::Dictionary{
                    {"archiveVersion", 1},
                    {"classes", plist::Value::Dictionary{}},
                    {"objectVersion", 50},
                    {"objects", plist::Value::Dictionary{}},
                    {"rootObject", rootObject ? toString(rootObject->getId()): ""}
                };

                for (const auto& object : objects)
                    result["objects"][toString(object->getId())] = object->encode();

                return result;
            }

            const OuzelProject& project;
            std::vector<std::unique_ptr<PBXObject>> objects;
            const PBXObject* rootObject;
        };
    }
}

#endif // OUZEL_XCODE_PROJECT_HPP
<|endoftext|>


<commit_before>#pragma once

#include <cmath>
#include <array>
#include <vector>

#include "zmsg_cmm.hpp"

namespace zmsg {

/**
 * \brief typedefs
 */
typedef signed char CHAR;
typedef unsigned char UCHAR;

typedef signed short SHORT;
typedef unsigned short USHORT;

typedef int8_t INT8;
typedef uint8_t UINT8;
typedef int16_t INT16;
typedef uint16_t UINT16;
typedef int32_t INT32;
typedef uint32_t UINT32;

typedef signed long LONG;
typedef unsigned long ULONG;

typedef float FLOAT;

typedef double DOUBLE;

typedef bool BOOL;

typedef void VOID;

} /* namespace zmsg */

/**
 * \brief bool image
 */
struct bool_img {
	bool_img()
	: width(0)
	, height(0)
	, data()
	{
	}

	uint16_t width;
	uint16_t height;
	std::vector<bool> data;
public:
	ZMSG_PU(width, height, data)
};

/**
 * \brief img fiber defect description
 */
typedef uint32_t ifd_t;

static constexpr ifd_t ifd_end_crude = 0x1;
static constexpr ifd_t ifd_horizontal_angle = 0x2;
static constexpr ifd_t ifd_vertical_angle = 0x4;

static constexpr ifd_t ifd_cant_identify = 0x80000000;

typedef struct ifd_line final {
	ifd_t  dbmp;

	/// \note all angles' unit are degree
	double h_angle;
	double v_angle;

	int32_t wrap_diameter;	/// unit: pixel

	ifd_line()
	: dbmp(0)
	, h_angle(0)
	, v_angle(0)
	, wrap_diameter(0)
	{
	}

	operator bool() const
	{
		return dbmp;
	}

	bool check(ifd_t msk) const
	{
		return (dbmp & msk);
	}
public:
	ZMSG_PU(dbmp, h_angle, v_angle, wrap_diameter)
} ifd_line_t;

typedef struct img_defects final {
	ifd_line_t yzl;
	ifd_line_t yzr;
	ifd_line_t xzl;
	ifd_line_t xzr;

	/// the image contain missed corner info
	bool_img yz_img;
	bool_img xz_img;

	img_defects()
	: yzl(), yzr(), xzl(), xzr()
	, yz_img(), xz_img()
	{
	}

	operator bool() const
	{
		return (yzl || yzr || xzl || xzr);
	}

	bool check(ifd_t msk) const
	{
		return (yzl.check(msk)
			|| yzr.check(msk)
			|| xzl.check(msk)
			|| xzr.check(msk));
	}

	double left_cut_angle(void) const
	{
		return std::max(yzl.v_angle, xzl.v_angle);
	}

	double right_cut_angle(void) const
	{
		return std::max(yzr.v_angle, xzr.v_angle);
	}
public:
	ZMSG_PU(yzl, yzr, xzl, xzr, yz_img, xz_img)
} img_defects_t;

/**
 * \biref fiber recognition infomation
 */
typedef struct final {
	uint32_t wrap_diameter;	/// unit: nm
	uint32_t core_diameter; /// unit: nm
public:
	ZMSG_PU(wrap_diameter, core_diameter)
} fiber_rec_info_t;

/**
 * \brief service fs state
 * \note all states mean enter this state.
 */
enum class svc_fs_state_t : uint16_t {
	fs_reseting,
	fs_idle,
	fs_ready,

	fs_entering,
	fs_push1,
	fs_calibrating,
	fs_waiting,
	fs_clring,
	fs_defect_detecting,
	fs_push2,
	fs_pause1,
	fs_precise_calibrating,
	fs_pause2,
	fs_pre_splice,
	fs_discharge1,
	fs_discharge2,
	fs_discharge_manual,
	fs_loss_estimating,
	fs_tension_testing,
	fs_finished,
};

/**
 * \brief service heat state
 */
enum class svc_heat_state_t : uint16_t {
	heat_ready,
	heat_ascending,
	heat_stabling,
	heat_descending,
};

/**
 * \brief motor id
 */
enum motorId_t : uint8_t {
	LZ = 0,	// left z
	RZ,	// right z
	X,	// x
	Y,	// y

	NUM,	// total number
};

/**
 * \brief fusion splice display mode
 */
enum class fs_display_mode_t : uint8_t {
	X = 0x0,	/// only x
	Y,		/// only y
	TB,		/// top <-> bottom
	LR,		/// left <-> right
	NO,		/// no

	max,		/// number
};

/**
 * \brief fusion splice related error code
 */
enum class fs_err_t : uint8_t {
	success,
	cover_openned,
	no_fiber,
	fiber_defect,
	fiber_cross_over,
	fiber_off_center,
	img_brightness,
	abnormal_arc,
	tense_test_fail,
	fiber_broken,

	arc_time_zero,
};

/**
 * \brief regular test related error code
 */
enum class rt_err_t : uint8_t {
	success,
};

/**
 * \brief dust check related error code
 */
enum class dc_err_t : uint8_t {
	success,
	cover_openned,
	img_brightness,
};

/**
 * \brief motor test related error code
 */
enum class mt_err_t : uint8_t {
	success,
	cover_openned,
	no_fiber,
	fiber_defect,
	fiber_cross_over,
	fiber_off_center,
	img_brightness,
	abnormal_arc,
	push_timeout,
	calibrate_timeout,
	reset_timeout,

	arc_time_zero,
};

/**
 * \brief stablize electrode error code
 */
enum class se_err_t : uint8_t {
	success,
	cover_openned,
	no_fiber,
	fiber_defect,
	fiber_cross_over,
	fiber_off_center,
	img_brightness,
	abnormal_arc,

	arc_time_zero,
};

/**
 * \brief discharg adjust error code
 */
enum class da_err_t : uint8_t {
	success,
	cover_openned,
	no_fiber,
	fiber_defect,
	fiber_cross_over,
	fiber_off_center,
	img_brightness,
	abnormal_arc,

	revise1_mag,
	revise2_mag,

	arc_time_zero,
};

/**
 * \brief heat related error code
 */
enum class heat_err_t : uint8_t {
	success,
};

/**
 * \brief led id
 */
enum ledId_t : uint8_t {
	CMOS_X = 0x0,
	CMOS_Y,

	LED_NUM,
};

/**
 * \brief discharge_data_t, used for discharge revising
 */
typedef struct {
	struct {
		uint16_t x;
		double   y;		/// unit: um
	public:
		ZMSG_PU(x, y)
	} p[2];

	double temp;	/// unit: degree centigrade

	bool empty() const
	{
		return (p[0].x == p[1].x);
	}
public:
	ZMSG_PU(p, temp)
} discharge_data_t;

/**
 * \brief fusion splice pattern
 */
enum class fs_pattern_t : uint8_t {
	automatic = 0x0,
	calibrate,
	normal,
	special,
};

/**
 * \brief loss estimate mode
 */
enum class loss_estimate_mode_t : uint8_t {
	off = 0x0,
	accurate,
	core,
	cladding,
};
<commit_msg>zmsg: add 'init' interface for fiber defect<commit_after>#pragma once

#include <cmath>
#include <array>
#include <vector>

#include "zmsg_cmm.hpp"

namespace zmsg {

/**
 * \brief typedefs
 */
typedef signed char CHAR;
typedef unsigned char UCHAR;

typedef signed short SHORT;
typedef unsigned short USHORT;

typedef int8_t INT8;
typedef uint8_t UINT8;
typedef int16_t INT16;
typedef uint16_t UINT16;
typedef int32_t INT32;
typedef uint32_t UINT32;

typedef signed long LONG;
typedef unsigned long ULONG;

typedef float FLOAT;

typedef double DOUBLE;

typedef bool BOOL;

typedef void VOID;

} /* namespace zmsg */

/**
 * \brief bool image
 */
struct bool_img {
	bool_img()
	: width(0)
	, height(0)
	, data()
	{
	}

	void init(void)
	{
		this->width = 0;
		this->height = 0;
		this->data.clear();
	}

	uint16_t width;
	uint16_t height;
	std::vector<bool> data;
public:
	ZMSG_PU(width, height, data)
};

/**
 * \brief img fiber defect description
 */
typedef uint32_t ifd_t;

static constexpr ifd_t ifd_end_crude = 0x1;
static constexpr ifd_t ifd_horizontal_angle = 0x2;
static constexpr ifd_t ifd_vertical_angle = 0x4;

static constexpr ifd_t ifd_cant_identify = 0x80000000;

typedef struct ifd_line final {
	ifd_t  dbmp;

	/// \note all angles' unit are degree
	double h_angle;
	double v_angle;

	int32_t wrap_diameter;	/// unit: pixel

	ifd_line()
	: dbmp(0)
	, h_angle(0)
	, v_angle(0)
	, wrap_diameter(0)
	{
	}

	void init(void)
	{
		this->dbmp = 0;
		this->h_angle = 0;
		this->v_angle = 0;
		this->wrap_diameter = 0;
	}

	operator bool() const
	{
		return dbmp;
	}

	bool check(ifd_t msk) const
	{
		return (dbmp & msk);
	}
public:
	ZMSG_PU(dbmp, h_angle, v_angle, wrap_diameter)
} ifd_line_t;

typedef struct img_defects final {
	ifd_line_t yzl;
	ifd_line_t yzr;
	ifd_line_t xzl;
	ifd_line_t xzr;

	/// the image contain missed corner info
	bool_img yz_img;
	bool_img xz_img;

	img_defects()
	: yzl(), yzr(), xzl(), xzr()
	, yz_img(), xz_img()
	{
	}

	void init(void)
	{
		this->yzl.init();
		this->yzr.init();
		this->xzl.init();
		this->xzr.init();
		this->yz_img.init();
		this->xz_img.init();
	}

	operator bool() const
	{
		return (yzl || yzr || xzl || xzr);
	}

	bool check(ifd_t msk) const
	{
		return (yzl.check(msk)
			|| yzr.check(msk)
			|| xzl.check(msk)
			|| xzr.check(msk));
	}

	double left_cut_angle(void) const
	{
		return std::max(yzl.v_angle, xzl.v_angle);
	}

	double right_cut_angle(void) const
	{
		return std::max(yzr.v_angle, xzr.v_angle);
	}
public:
	ZMSG_PU(yzl, yzr, xzl, xzr, yz_img, xz_img)
} img_defects_t;

/**
 * \biref fiber recognition infomation
 */
typedef struct final {
	uint32_t wrap_diameter;	/// unit: nm
	uint32_t core_diameter; /// unit: nm
public:
	ZMSG_PU(wrap_diameter, core_diameter)
} fiber_rec_info_t;

/**
 * \brief service fs state
 * \note all states mean enter this state.
 */
enum class svc_fs_state_t : uint16_t {
	fs_reseting,
	fs_idle,
	fs_ready,

	fs_entering,
	fs_push1,
	fs_calibrating,
	fs_waiting,
	fs_clring,
	fs_defect_detecting,
	fs_push2,
	fs_pause1,
	fs_precise_calibrating,
	fs_pause2,
	fs_pre_splice,
	fs_discharge1,
	fs_discharge2,
	fs_discharge_manual,
	fs_loss_estimating,
	fs_tension_testing,
	fs_finished,
};

/**
 * \brief service heat state
 */
enum class svc_heat_state_t : uint16_t {
	heat_ready,
	heat_ascending,
	heat_stabling,
	heat_descending,
};

/**
 * \brief motor id
 */
enum motorId_t : uint8_t {
	LZ = 0,	// left z
	RZ,	// right z
	X,	// x
	Y,	// y

	NUM,	// total number
};

/**
 * \brief fusion splice display mode
 */
enum class fs_display_mode_t : uint8_t {
	X = 0x0,	/// only x
	Y,		/// only y
	TB,		/// top <-> bottom
	LR,		/// left <-> right
	NO,		/// no

	max,		/// number
};

/**
 * \brief fusion splice related error code
 */
enum class fs_err_t : uint8_t {
	success,
	cover_openned,
	no_fiber,
	fiber_defect,
	fiber_cross_over,
	fiber_off_center,
	img_brightness,
	abnormal_arc,
	tense_test_fail,
	fiber_broken,

	arc_time_zero,
};

/**
 * \brief regular test related error code
 */
enum class rt_err_t : uint8_t {
	success,
};

/**
 * \brief dust check related error code
 */
enum class dc_err_t : uint8_t {
	success,
	cover_openned,
	img_brightness,
};

/**
 * \brief motor test related error code
 */
enum class mt_err_t : uint8_t {
	success,
	cover_openned,
	no_fiber,
	fiber_defect,
	fiber_cross_over,
	fiber_off_center,
	img_brightness,
	abnormal_arc,
	push_timeout,
	calibrate_timeout,
	reset_timeout,

	arc_time_zero,
};

/**
 * \brief stablize electrode error code
 */
enum class se_err_t : uint8_t {
	success,
	cover_openned,
	no_fiber,
	fiber_defect,
	fiber_cross_over,
	fiber_off_center,
	img_brightness,
	abnormal_arc,

	arc_time_zero,
};

/**
 * \brief discharg adjust error code
 */
enum class da_err_t : uint8_t {
	success,
	cover_openned,
	no_fiber,
	fiber_defect,
	fiber_cross_over,
	fiber_off_center,
	img_brightness,
	abnormal_arc,

	revise1_mag,
	revise2_mag,

	arc_time_zero,
};

/**
 * \brief heat related error code
 */
enum class heat_err_t : uint8_t {
	success,
};

/**
 * \brief led id
 */
enum ledId_t : uint8_t {
	CMOS_X = 0x0,
	CMOS_Y,

	LED_NUM,
};

/**
 * \brief discharge_data_t, used for discharge revising
 */
typedef struct {
	struct {
		uint16_t x;
		double   y;		/// unit: um
	public:
		ZMSG_PU(x, y)
	} p[2];

	double temp;	/// unit: degree centigrade

	bool empty() const
	{
		return (p[0].x == p[1].x);
	}
public:
	ZMSG_PU(p, temp)
} discharge_data_t;

/**
 * \brief fusion splice pattern
 */
enum class fs_pattern_t : uint8_t {
	automatic = 0x0,
	calibrate,
	normal,
	special,
};

/**
 * \brief loss estimate mode
 */
enum class loss_estimate_mode_t : uint8_t {
	off = 0x0,
	accurate,
	core,
	cladding,
};
<|endoftext|>


<commit_before>/***************************************
** Tsunagari Tile Engine              **
** character.cpp                      **
** Copyright 2011-2014 Michael Reiley **
** Copyright 2011-2019 Paul Merrill   **
***************************************/

// **********
// 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 "core/character.h"

#include "core/area.h"
#include "core/client-conf.h"
#include "core/sounds.h"
#include "core/tile.h"

Character::Character() noexcept
        : nowalkFlags(TILE_NOWALK | TILE_NOWALK_NPC),
          nowalkExempt(0),
          fromCoord({0.0, 0.0, 0.0}),
          fromTile(nullptr),
          destTile(nullptr),
          destExit(nullptr) {
    enterTile();
}

void
Character::tick(time_t dt) noexcept {
    Entity::tick(dt);

    switch (Conf::moveMode) {
    case Conf::TURN:
        // Characters don't do anything on tick() for TURN mode.
        break;
    case Conf::TILE:
        moveTowardDestination(dt);
        break;
    case Conf::NOTILE:
        assert_(false && "not implemented");
        break;
    }
}

void
Character::turn() noexcept {}

void
Character::destroy() noexcept {
    leaveTile();
    Entity::destroy();
}

icoord
Character::getTileCoords_i() const noexcept {
    return area->grid.virt2phys(r);
}

vicoord
Character::getTileCoords_vi() const noexcept {
    return area->grid.virt2virt(r);
}

void
Character::setTileCoords(int x, int y) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(vicoord{x, y, r.z});
    enterTile();
}

void
Character::setTileCoords(int x, int y, double z) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(vicoord{x, y, z});
    enterTile();
}

void
Character::setTileCoords(icoord phys) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.phys2virt_r(phys);
    enterTile();
}

void
Character::setTileCoords(vicoord virt) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(virt);
    enterTile();
}

void
Character::setTileCoords(rcoord virt) noexcept {
    leaveTile();
    redraw = true;
    r = virt;
    enterTile();
}

const Tile*
Character::getTile() const noexcept {
    return area ? area->grid.getTile(r) : nullptr;
}

Tile*
Character::getTile() noexcept {
    return area ? area->grid.getTile(r) : nullptr;
}

void
Character::setArea(Area* area, vicoord position) noexcept {
    leaveTile();
    Entity::setArea(area);
    r = area->grid.virt2virt(position);
    enterTile();
    redraw = true;
}

void
Character::moveByTile(ivec2 delta) noexcept {
    if (moving) {
        return;
    }

    setFacing(delta);

    icoord dest = moveDest(facing);

    fromTile = getTile();
    destTile = area->grid.getTile(dest);
    setDestinationCoordinate(area->grid.phys2virt_r(dest));

    destExit = nullptr;
    if (fromTile) {
        destExit = &fromTile->exitAt(delta);
    }
    else if (destTile) {
        destExit = &destTile->exits[EXIT_NORMAL];
    }

    if (!canMove(dest)) {
        setAnimationStanding();
        return;
    }

    setAnimationMoving();
    moving = true;

    // Process triggers.
    runTileExitScript();
    if (fromTile) {
        area->runLeaveScript(area->grid.virt2phys(fromCoord), this);
    }

    // Modify tile's entity count.
    leaveTile(fromTile);
    enterTile(destTile);

    Sounds::play(soundPaths[StringView("step")]);

    switch (Conf::moveMode) {
    case Conf::TURN:
        // Movement is instantaneous.
        redraw = true;
        r = destCoord;
        moving = false;
        setAnimationStanding();
        arrived();
        break;
    case Conf::TILE:
    case Conf::NOTILE:
        // Movement happens in Entity::moveTowardDestination() during
        // tick().
        break;
    }
}

icoord
Character::moveDest(ivec2 facing) noexcept {
    Tile* tile = getTile();
    icoord here = getTileCoords_i();

    if (tile) {
        // Handle layermod.
        return tile->moveDest(area, here, facing);
    }
    else {
        return here + icoord{facing.x, facing.y, 0};
    }
}

bool
Character::canMove(icoord dest) noexcept {
    if (destExit && *destExit) {
        // We can always take exits as long as we can take exits.
        // (Even if they would cause us to be out of bounds.)
        if (nowalkExempt & TILE_NOWALK_EXIT) {
            return true;
        }
    }

    bool inBounds = area->grid.inBounds(dest);
    if (destTile && inBounds) {
        // Tile is inside map. Can we move?
        if (nowalked(*destTile)) {
            return false;
        }
        if (destTile->entCnt) {
            // Space is occupied by another Entity.
            return false;
        }

        return true;
    }

    // The tile is legitimately off the map.
    return nowalkExempt & TILE_NOWALK_AREA_BOUND;
}

bool
Character::nowalked(Tile& t) noexcept {
    unsigned flags = nowalkFlags & ~nowalkExempt;
    return t.flags & flags;
}

void
Character::arrived() noexcept {
    Entity::arrived();

    if (destTile) {
        Optional<double> layermod = destTile->layermods[EXIT_NORMAL];
        if (layermod) {
            r.z = *layermod;
        }
    }

    // Process triggers.
    if (destTile) {
        area->runEnterScript(area->grid.virt2phys(destCoord), this);
    }

    runTileEntryScript();

    // TODO: move teleportation here
    /*
     * if (onExit()) {
     *      leaveTile();
     *      moveArea(getExit());
     *      Entity::arrived();
     *      enterTile();
     * }
     */
}

void
Character::leaveTile() noexcept {
    leaveTile(getTile());
}

void
Character::leaveTile(Tile* t) noexcept {
    if (t) {
        t->entCnt--;
    }
}

void
Character::enterTile() noexcept {
    enterTile(getTile());
}

void
Character::enterTile(Tile* t) noexcept {
    if (t) {
        t->entCnt++;
    }
}

void
Character::runTileExitScript() noexcept {
    // if (!tileExitScript) {
    //     return;
    // }
    // pythonSetGlobal("Area", area);
    // pythonSetGlobal("Character", this);
    // pythonSetGlobal("Tile", getTile());
    // tileExitScript->invoke();
}

void
Character::runTileEntryScript() noexcept {
    // if (!tileEntryScript) {
    //     return;
    // }
    // pythonSetGlobal("Area", area);
    // pythonSetGlobal("Character", this);
    // pythonSetGlobal("Tile", getTile());
    // tileEntryScript->invoke();
}
<commit_msg>core/character: Fix MSVC 2015 warnings<commit_after>/***************************************
** Tsunagari Tile Engine              **
** character.cpp                      **
** Copyright 2011-2014 Michael Reiley **
** Copyright 2011-2019 Paul Merrill   **
***************************************/

// **********
// 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 "core/character.h"

#include "core/area.h"
#include "core/client-conf.h"
#include "core/sounds.h"
#include "core/tile.h"

Character::Character() noexcept
        : nowalkFlags(TILE_NOWALK | TILE_NOWALK_NPC),
          nowalkExempt(0),
          fromCoord({0.0, 0.0, 0.0}),
          fromTile(nullptr),
          destTile(nullptr),
          destExit(nullptr) {
    enterTile();
}

void
Character::tick(time_t dt) noexcept {
    Entity::tick(dt);

    switch (Conf::moveMode) {
    case Conf::TURN:
        // Characters don't do anything on tick() for TURN mode.
        break;
    case Conf::TILE:
        moveTowardDestination(dt);
        break;
    case Conf::NOTILE:
        assert_(false && "not implemented");
        break;
    }
}

void
Character::turn() noexcept {}

void
Character::destroy() noexcept {
    leaveTile();
    Entity::destroy();
}

icoord
Character::getTileCoords_i() const noexcept {
    return area->grid.virt2phys(r);
}

vicoord
Character::getTileCoords_vi() const noexcept {
    return area->grid.virt2virt(r);
}

void
Character::setTileCoords(int x, int y) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(vicoord{x, y, r.z});
    enterTile();
}

void
Character::setTileCoords(int x, int y, double z) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(vicoord{x, y, z});
    enterTile();
}

void
Character::setTileCoords(icoord phys) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.phys2virt_r(phys);
    enterTile();
}

void
Character::setTileCoords(vicoord virt) noexcept {
    leaveTile();
    redraw = true;
    r = area->grid.virt2virt(virt);
    enterTile();
}

void
Character::setTileCoords(rcoord virt) noexcept {
    leaveTile();
    redraw = true;
    r = virt;
    enterTile();
}

const Tile*
Character::getTile() const noexcept {
    return area ? area->grid.getTile(r) : nullptr;
}

Tile*
Character::getTile() noexcept {
    return area ? area->grid.getTile(r) : nullptr;
}

void
Character::setArea(Area* area, vicoord position) noexcept {
    leaveTile();
    Entity::setArea(area);
    r = area->grid.virt2virt(position);
    enterTile();
    redraw = true;
}

void
Character::moveByTile(ivec2 delta) noexcept {
    if (moving) {
        return;
    }

    setFacing(delta);

    icoord dest = moveDest(facing);

    fromTile = getTile();
    destTile = area->grid.getTile(dest);
    setDestinationCoordinate(area->grid.phys2virt_r(dest));

    destExit = nullptr;
    if (fromTile) {
        destExit = &fromTile->exitAt(delta);
    }
    else if (destTile) {
        destExit = &destTile->exits[EXIT_NORMAL];
    }

    if (!canMove(dest)) {
        setAnimationStanding();
        return;
    }

    setAnimationMoving();
    moving = true;

    // Process triggers.
    runTileExitScript();
    if (fromTile) {
        area->runLeaveScript(area->grid.virt2phys(fromCoord), this);
    }

    // Modify tile's entity count.
    leaveTile(fromTile);
    enterTile(destTile);

    Sounds::play(soundPaths[StringView("step")]);

    switch (Conf::moveMode) {
    case Conf::TURN:
        // Movement is instantaneous.
        redraw = true;
        r = destCoord;
        moving = false;
        setAnimationStanding();
        arrived();
        break;
    case Conf::TILE:
    case Conf::NOTILE:
        // Movement happens in Entity::moveTowardDestination() during
        // tick().
        break;
    }
}

icoord
Character::moveDest(ivec2 facing) noexcept {
    Tile* tile = getTile();
    icoord here = getTileCoords_i();

    if (tile) {
        // Handle layermod.
        return tile->moveDest(area, here, facing);
    }
    else {
        return here + icoord{facing.x, facing.y, 0};
    }
}

bool
Character::canMove(icoord dest) noexcept {
    if (destExit && *destExit) {
        // We can always take exits as long as we can take exits.
        // (Even if they would cause us to be out of bounds.)
        if (nowalkExempt & TILE_NOWALK_EXIT) {
            return true;
        }
    }

    bool inBounds = area->grid.inBounds(dest);
    if (destTile && inBounds) {
        // Tile is inside map. Can we move?
        if (nowalked(*destTile)) {
            return false;
        }
        if (destTile->entCnt) {
            // Space is occupied by another Entity.
            return false;
        }

        return true;
    }

    // The tile is legitimately off the map.
    return (nowalkExempt & TILE_NOWALK_AREA_BOUND) != 0;
}

bool
Character::nowalked(Tile& t) noexcept {
    unsigned flags = nowalkFlags & ~nowalkExempt;
    return (t.flags & flags) != 0;
}

void
Character::arrived() noexcept {
    Entity::arrived();

    if (destTile) {
        Optional<double> layermod = destTile->layermods[EXIT_NORMAL];
        if (layermod) {
            r.z = *layermod;
        }
    }

    // Process triggers.
    if (destTile) {
        area->runEnterScript(area->grid.virt2phys(destCoord), this);
    }

    runTileEntryScript();

    // TODO: move teleportation here
    /*
     * if (onExit()) {
     *      leaveTile();
     *      moveArea(getExit());
     *      Entity::arrived();
     *      enterTile();
     * }
     */
}

void
Character::leaveTile() noexcept {
    leaveTile(getTile());
}

void
Character::leaveTile(Tile* t) noexcept {
    if (t) {
        t->entCnt--;
    }
}

void
Character::enterTile() noexcept {
    enterTile(getTile());
}

void
Character::enterTile(Tile* t) noexcept {
    if (t) {
        t->entCnt++;
    }
}

void
Character::runTileExitScript() noexcept {
    // if (!tileExitScript) {
    //     return;
    // }
    // pythonSetGlobal("Area", area);
    // pythonSetGlobal("Character", this);
    // pythonSetGlobal("Tile", getTile());
    // tileExitScript->invoke();
}

void
Character::runTileEntryScript() noexcept {
    // if (!tileEntryScript) {
    //     return;
    // }
    // pythonSetGlobal("Area", area);
    // pythonSetGlobal("Character", this);
    // pythonSetGlobal("Tile", getTile());
    // tileEntryScript->invoke();
}
<|endoftext|>


<commit_before>#pragma once

#include <iostream>

#define PI 3.1415926535897932
#define TWOPI 2.0*PI
#define HPI 0.5*PI
#define RPI 1.0/PI
#define RTWOPI 1.0/TWOPI
#define FPI 4.0*PI
#define RFPI 1.0/(FPI)

namespace mocc {
    // Surface and direction indexing
    enum Surface {
        EAST  = 0,
        NORTH = 1,
        WEST  = 2,
        SOUTH = 3,
        TOP = 4,
        BOTTOM = 5,
        INVALID = 6
    };

    enum class Direction : unsigned char {
        EAST  = 0,
        NORTH = 1,
        WEST  = 2,
        SOUTH = 3,
        TOP = 4,
        BOTTOM = 5,
        NE = 6,
        NW = 7,
        SW = 8,
        SE = 9,
        INVALID = 10
    };

    extern const Surface AllSurfaces[6];

    enum class Normal : unsigned char {
        X_NORM = 0,
        Y_NORM = 1,
        Z_NORM = 2
    };

    extern const Normal AllNormals[3];

    // Boundary condition enumeration
    enum class Boundary {
        /**
         * Zero incoming flux
         */
        VACUUM,
        /**
         * Reflected incoming flux
         */
        REFLECT,
        /**
         * Incoming flux communicated between domain nodes
         */
        PARALLEL,
        /**
         * Flux exiting one face enters the opposite face, same angle
         */
        PERIODIC,
        INVALID
    };

    enum class TraceDir {
        FW,
        BW
    };

    std::ostream& operator<<(std::ostream& os, const Surface s );

    std::ostream& operator<<(std::ostream& os, const Boundary b );

    std::ostream& operator<<(std::ostream& os, const Normal n );

    Normal surface_to_normal( Surface s );

}
<commit_msg>Protect all of the preprocessor defined constants with ()<commit_after>#pragma once

#include <iostream>

#define PI 3.1415926535897932
#define TWOPI (2.0*PI)
#define HPI (0.5*PI)
#define RPI (1.0/PI)
#define RTWOPI (1.0/TWOPI)
#define FPI (4.0*PI)
#define RFPI (1.0/FPI)

namespace mocc {
    // Surface and direction indexing
    enum Surface {
        EAST  = 0,
        NORTH = 1,
        WEST  = 2,
        SOUTH = 3,
        TOP = 4,
        BOTTOM = 5,
        INVALID = 6
    };

    enum class Direction : unsigned char {
        EAST  = 0,
        NORTH = 1,
        WEST  = 2,
        SOUTH = 3,
        TOP = 4,
        BOTTOM = 5,
        NE = 6,
        NW = 7,
        SW = 8,
        SE = 9,
        INVALID = 10
    };

    extern const Surface AllSurfaces[6];

    enum class Normal : unsigned char {
        X_NORM = 0,
        Y_NORM = 1,
        Z_NORM = 2
    };

    extern const Normal AllNormals[3];

    // Boundary condition enumeration
    enum class Boundary {
        /**
         * Zero incoming flux
         */
        VACUUM,
        /**
         * Reflected incoming flux
         */
        REFLECT,
        /**
         * Incoming flux communicated between domain nodes
         */
        PARALLEL,
        /**
         * Flux exiting one face enters the opposite face, same angle
         */
        PERIODIC,
        INVALID
    };

    enum class TraceDir {
        FW,
        BW
    };

    std::ostream& operator<<(std::ostream& os, const Surface s );

    std::ostream& operator<<(std::ostream& os, const Boundary b );

    std::ostream& operator<<(std::ostream& os, const Normal n );

    Normal surface_to_normal( Surface s );

}
<|endoftext|>