text:
#include <oslo/boost/asio/bind_executor.hpp>
#include <oslo/boost/asio/local/stream_protocol.hpp>
#include <oslo/boost/asio/read.hpp>
#include <oslo/boost/asio/strand.hpp>
#include <oslo/lib/config.hpp>
#include <oslo/lib/ipc.hpp>
#include <oslo/lib/locks.hpp>
#include <oslo/lib/threading.hpp>
#include <oslo/lib/timer.hpp>
#include <oslo/node/common.hpp>
#include <oslo/node/ipc/action_handler.hpp>
#include <oslo/node/ipc/flatbuffers_handler.hpp>
#include <oslo/node/ipc/flatbuffers_util.hpp>
#include <oslo/node/ipc/ipc_server.hpp>
#include <oslo/node/json_handler.hpp>
#include <oslo/node/node.hpp>

#include <boost/asio/signal_set.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/property_tree/json_parser.hpp>

#include <atomic>
#include <chrono>
#include <list>

#include <flatbuffers/flatbuffers.h>

using namespace boost::log;

namespace
{
/**
 * A session manages an inbound connection over which messages are exchanged.
 */
template <typename SOCKET_TYPE>
class session final : public oslo::ipc::socket_base, public std::enable_shared_from_this<session<SOCKET_TYPE>>
{
public:
	session (oslo::ipc::ipc_server & server_a, boost::asio::io_context & io_ctx_a, oslo::ipc::ipc_config_transport & config_transport_a) :
	socket_base (io_ctx_a),
	server (server_a), node (server_a.node), session_id (server_a.id_dispenser.fetch_add (1)),
	io_ctx (io_ctx_a), strand (io_ctx_a.get_executor ()), socket (io_ctx_a), config_transport (config_transport_a)
	{
		if (node.config.logging.log_ipc ())
		{
			node.logger.always_log ("IPC: created session with id: ", session_id.load ());
		}
	}

	~session ()
	{
		close ();
	}

	SOCKET_TYPE & get_socket ()
	{
		return socket;
	}

	std::shared_ptr<oslo::ipc::subscriber> get_subscriber ()
	{
		class subscriber_impl final : public oslo::ipc::subscriber, public std::enable_shared_from_this<subscriber_impl>
		{
		public:
			subscriber_impl (std::shared_ptr<session> const & session_a) :
			session_m (session_a)
			{
			}
			virtual void async_send_message (uint8_t const * data_a, size_t length_a, std::function<void(oslo::error const &)> broadcast_completion_handler_a) override
			{
				if (auto session_l = session_m.lock ())
				{
					auto big_endian_length = std::make_shared<uint32_t> (boost::endian::native_to_big (static_cast<uint32_t> (length_a)));
					boost::array<boost::asio::const_buffer, 2> buffers = {
						boost::asio::buffer (big_endian_length.get (), sizeof (std::uint32_t)),
						boost::asio::buffer (data_a, length_a)
					};

					session_l->queued_write (buffers, [broadcast_completion_handler_a, big_endian_length](boost::system::error_code const & ec_a, size_t size_a) {
						if (broadcast_completion_handler_a)
						{
							oslo::error error_l (ec_a);
							broadcast_completion_handler_a (error_l);
						}
					});
				}
			}

			uint64_t get_id () const override
			{
				uint64_t id{ 0 };
				if (auto session_l = session_m.lock ())
				{
					id = session_l->session_id;
				}
				return id;
			}

			std::string get_service_name () const override
			{
				std::string name{ 0 };
				if (auto session_l = session_m.lock ())
				{
					name = session_l->service_name;
				}
				return name;
			}

			void set_service_name (std::string const & service_name_a) override
			{
				if (auto session_l = session_m.lock ())
				{
					session_l->service_name = service_name_a;
				}
			}

			oslo::ipc::payload_encoding get_active_encoding () const override
			{
				oslo::ipc::payload_encoding encoding{ oslo::ipc::payload_encoding::flatbuffers };
				if (auto session_l = session_m.lock ())
				{
					encoding = session_l->active_encoding;
				}
				return encoding;
			}

		private:
			std::weak_ptr<session> session_m;
		};

		static std::mutex subscriber_mutex;
		oslo::unique_lock<std::mutex> lock (subscriber_mutex);

		if (!subscriber)
		{
			subscriber = std::make_shared<subscriber_impl> (this->shared_from_this ());
		}
		return subscriber;
	}

	/** Write a fixed array of buffers through the queue. Once the last item is completed, the callback is invoked */
	template <std::size_t N>
	void queued_write (boost::array<boost::asio::const_buffer, N> & buffers, std::function<void(boost::system::error_code const &, size_t)> callback_a)
	{
		auto this_l (this->shared_from_this ());
		boost::asio::post (strand, boost::asio::bind_executor (strand, [buffers, callback_a, this_l]() {
			bool write_in_progress = !this_l->send_queue.empty ();
			auto queue_size = this_l->send_queue.size ();
			if (queue_size < this_l->queue_size_max)
			{
				for (size_t i = 0; i < N - 1; i++)
				{
					this_l->send_queue.emplace_back (queue_item{ buffers[i], nullptr });
				}
				this_l->send_queue.emplace_back (queue_item{ buffers[N - 1], callback_a });
			}
			if (!write_in_progress)
			{
				this_l->write_queued_messages ();
			}
		}));
	}

	/**
	 * Write to underlying socket. Writes goes through a queue protected by the strand. Thus, this function
	 * can be called concurrently with other writes.
	 * @note This function explicitely doesn't use oslo::shared_const_buffer, as buffers usually originate from Flatbuffers
	 * and copying into the shared_const_buffer vector would impose a significant overhead for large requests and responses.
	 */
	void queued_write (boost::asio::const_buffer const & buffer_a, std::function<void(boost::system::error_code const &, size_t)> callback_a)
	{
		auto this_l (this->shared_from_this ());
		boost::asio::post (strand, boost::asio::bind_executor (strand, [buffer_a, callback_a, this_l]() {
			bool write_in_progress = !this_l->send_queue.empty ();
			auto queue_size = this_l->send_queue.size ();
			if (queue_size < this_l->queue_size_max)
			{
				this_l->send_queue.emplace_back (queue_item{ buffer_a, callback_a });
			}
			if (!write_in_progress)
			{
				this_l->write_queued_messages ();
			}
		}));
	}

	void write_queued_messages ()
	{
		std::weak_ptr<session> this_w (this->shared_from_this ());
		auto msg (send_queue.front ());
		timer_start (std::chrono::seconds (config_transport.io_timeout));
		oslo::unsafe_async_write (socket, msg.buffer,
		boost::asio::bind_executor (strand,
		[msg, this_w](boost::system::error_code ec, std::size_t size_a) {
			if (auto this_l = this_w.lock ())
			{
				this_l->timer_cancel ();

				if (msg.callback)
				{
					msg.callback (ec, size_a);
				}

				this_l->send_queue.pop_front ();
				if (!ec && !this_l->send_queue.empty ())
				{
					this_l->write_queued_messages ();
				}
			}
		}));
	}

	/**
	 * Async read of exactly \p size_a bytes. The callback is invoked only when all the data is available and
	 * no error has occurred. On error, the error is logged, the read cycle stops and the session ends. Clients
	 * are expected to implement reconnect logic.
	 */
	void async_read_exactly (void * buff_a, size_t size_a, std::function<void()> const & callback_a)
	{
		async_read_exactly (buff_a, size_a, std::chrono::seconds (config_transport.io_timeout), callback_a);
	}

	/**
	 * Async read of exactly \p size_a bytes and a specific \p timeout_a.
	 * @see async_read_exactly (void *, size_t, std::function<void()>)
	 */
	void async_read_exactly (void * buff_a, size_t size_a, std::chrono::seconds timeout_a, std::function<void()> const & callback_a)
	{
		timer_start (timeout_a);
		auto this_l (this->shared_from_this ());
		boost::asio::async_read (socket,
		boost::asio::buffer (buff_a, size_a),
		boost::asio::transfer_exactly (size_a),
		boost::asio::bind_executor (strand,
		[this_l, callback_a](boost::system::error_code const & ec, size_t bytes_transferred_a) {
			this_l->timer_cancel ();
			if (ec == boost::asio::error::broken_pipe || ec == boost::asio::error::connection_aborted || ec == boost::asio::error::connection_reset || ec == boost::asio::error::connection_refused)
			{
				if (this_l->node.config.logging.log_ipc ())
				{
					this_l->node.logger.always_log (boost::str (boost::format ("IPC: error reading %1% ") % ec.message ()));
				}
			}
			else if (bytes_transferred_a > 0)
			{
				callback_a ();
			}
		}));
	}

	/** Handler for payload_encoding::json_legacy */
	void handle_json_query (bool allow_unsafe)
	{
		session_timer.restart ();
		auto request_id_l (std::to_string (server.id_dispenser.fetch_add (1)));

		// This is called when oslo::rpc_handler#process_request is done. We convert to
		// json and write the response to the ipc socket with a length prefix.
		auto this_l (this->shared_from_this ());
		auto response_handler_l ([this_l, request_id_l](std::string const & body) {
			auto big = boost::endian::native_to_big (static_cast<uint32_t> (body.size ()));
			auto buffer (std::make_shared<std::vector<uint8_t>> ());
			buffer->insert (buffer->end (), reinterpret_cast<std::uint8_t *> (&big), reinterpret_cast<std::uint8_t *> (&big) + sizeof (std::uint32_t));
			buffer->insert (buffer->end (), body.begin (), body.end ());
			if (this_l->node.config.logging.log_ipc ())
			{
				this_l->node.logger.always_log (boost::str (boost::format ("IPC/RPC request %1% completed in: %2% %3%") % request_id_l % this_l->session_timer.stop ().count () % this_l->session_timer.unit ()));
			}

			this_l->timer_start (std::chrono::seconds (this_l->config_transport.io_timeout));
			this_l->queued_write (boost::asio::buffer (buffer->data (), buffer->size ()), [this_l, buffer](boost::system::error_code const & error_a, size_t size_a) {
				this_l->timer_cancel ();
				if (!error_a)
				{
					this_l->read_next_request ();
				}
				else if (this_l->node.config.logging.log_ipc ())
				{
					this_l->node.logger.always_log ("IPC: Write failed: ", error_a.message ());
				}
			});

			// Do not call any member variables here (like session_timer) as it's possible that the next request may already be underway.
		});

		node.stats.inc (oslo::stat::type::ipc, oslo::stat::detail::invocations);
		auto body (std::string (reinterpret_cast<char *> (buffer.data ()), buffer.size ()));

		// Note that if the rpc action is async, the shared_ptr<json_handler> lifetime will be extended by the action handler
		auto handler (std::make_shared<oslo::json_handler> (node, server.node_rpc_config, body, response_handler_l, [& server = server]() {
			server.stop ();
			server.node.alarm.add (std::chrono::steady_clock::now () + std::chrono::seconds (3), [& io_ctx = server.node.alarm.io_ctx]() {
				io_ctx.stop ();
			});
		}));
		// For unsafe actions to be allowed, the unsafe encoding must be used AND the transport config must allow it
		handler->process_request (allow_unsafe && config_transport.allow_unsafe);
	}

	/** Async request reader */
	void read_next_request ()
	{
		auto this_l = this->shared_from_this ();

		// Await next request indefinitely
		buffer.resize (sizeof (buffer_size));
		async_read_exactly (buffer.data (), buffer.size (), std::chrono::seconds::max (), [this_l]() {
			auto encoding (this_l->buffer[oslo::ipc::preamble_offset::encoding]);
			this_l->active_encoding = static_cast<oslo::ipc::payload_encoding> (encoding);
			if (this_l->buffer[oslo::ipc::preamble_offset::lead] != 'N' || this_l->buffer[oslo::ipc::preamble_offset::reserved_1] != 0 || this_l->buffer[oslo::ipc::preamble_offset::reserved_2] != 0)
			{
				if (this_l->node.config.logging.log_ipc ())
				{
					this_l->node.logger.always_log ("IPC: Invalid preamble");
				}
			}
			else if (encoding == static_cast<uint8_t> (oslo::ipc::payload_encoding::json_v1) || encoding == static_cast<uint8_t> (oslo::ipc::payload_encoding::json_v1_unsafe))
			{
				auto allow_unsafe (encoding == static_cast<uint8_t> (oslo::ipc::payload_encoding::json_v1_unsafe));
				// Length of payload
				this_l->async_read_exactly (&this_l->buffer_size, sizeof (this_l->buffer_size), [this_l, allow_unsafe]() {
					boost::endian::big_to_native_inplace (this_l->buffer_size);
					this_l->buffer.resize (this_l->buffer_size);
					// Payload (ptree compliant JSON string)
					this_l->async_read_exactly (this_l->buffer.data (), this_l->buffer_size, [this_l, allow_unsafe]() {
						this_l->handle_json_query (allow_unsafe);
					});
				});
			}
			else if (encoding == static_cast<uint8_t> (oslo::ipc::payload_encoding::flatbuffers) || encoding == static_cast<uint8_t> (oslo::ipc::payload_encoding::flatbuffers_json))
			{
				// Length of payload
				this_l->async_read_exactly (&this_l->buffer_size, sizeof (this_l->buffer_size), [this_l, encoding]() {
					boost::endian::big_to_native_inplace (this_l->buffer_size);
					this_l->buffer.resize (this_l->buffer_size);
					// Payload (flatbuffers or flatbuffers mappable json)
					this_l->async_read_exactly (this_l->buffer.data (), this_l->buffer_size, [this_l, encoding]() {
						this_l->session_timer.restart ();

						// Lazily create one Flatbuffers handler instance per session
						if (!this_l->flatbuffers_handler)
						{
							this_l->flatbuffers_handler = std::make_shared<oslo::ipc::flatbuffers_handler> (this_l->node, this_l->server, this_l->get_subscriber (), this_l->node.config.ipc_config);
						}

						if (encoding == static_cast<uint8_t> (oslo::ipc::payload_encoding::flatbuffers_json))
						{
							this_l->flatbuffers_handler->process_json (this_l->buffer.data (), this_l->buffer_size, [this_l](std::shared_ptr<std::string> body) {
								if (this_l->node.config.logging.log_ipc ())
								{
									this_l->node.logger.always_log (boost::str (boost::format ("IPC/Flatbuffer request completed in: %1% %2%") % this_l->session_timer.stop ().count () % this_l->session_timer.unit ()));
								}

								auto big_endian_length = std::make_shared<uint32_t> (boost::endian::native_to_big (static_cast<uint32_t> (body->size ())));
								boost::array<boost::asio::const_buffer, 2> buffers = {
									boost::asio::buffer (big_endian_length.get (), sizeof (std::uint32_t)),
									boost::asio::buffer (body->data (), body->size ())
								};

								this_l->queued_write (buffers, [this_l, body, big_endian_length](boost::system::error_code const & error_a, size_t size_a) {
									if (!error_a)
									{
										this_l->read_next_request ();
									}
									else if (this_l->node.config.logging.log_ipc ())
									{
										this_l->node.logger.always_log ("IPC: Write failed: ", error_a.message ());
									}
								});
							});
						}
						else
						{
							this_l->flatbuffers_handler->process (this_l->buffer.data (), this_l->buffer_size, [this_l](std::shared_ptr<flatbuffers::FlatBufferBuilder> fbb) {
								if (this_l->node.config.logging.log_ipc ())
								{
									this_l->node.logger.always_log (boost::str (boost::format ("IPC/Flatbuffer request completed in: %1% %2%") % this_l->session_timer.stop ().count () % this_l->session_timer.unit ()));
								}

								auto big_endian_length = std::make_shared<uint32_t> (boost::endian::native_to_big (static_cast<uint32_t> (fbb->GetSize ())));
								boost::array<boost::asio::const_buffer, 2> buffers = {
									boost::asio::buffer (big_endian_length.get (), sizeof (std::uint32_t)),
									boost::asio::buffer (fbb->GetBufferPointer (), fbb->GetSize ())
								};

								this_l->queued_write (buffers, [this_l, fbb, big_endian_length](boost::system::error_code const & error_a, size_t size_a) {
									if (!error_a)
									{
										this_l->read_next_request ();
									}
									else if (this_l->node.config.logging.log_ipc ())
									{
										this_l->node.logger.always_log ("IPC: Write failed: ", error_a.message ());
									}
								});
							});
						}
					});
				});
			}
			else if (this_l->node.config.logging.log_ipc ())
			{
				this_l->node.logger.always_log ("IPC: Unsupported payload encoding");
			}
		});
	}

	/** Shut down and close socket. This is also called if the timer expires. */
	void close ()
	{
		boost::system::error_code ec_ignored;
		socket.shutdown (boost::asio::ip::tcp::socket::shutdown_both, ec_ignored);
		socket.close (ec_ignored);
	}

private:
	/** Holds the buffer and callback for queued writes */
	class queue_item
	{
	public:
		boost::asio::const_buffer buffer;
		std::function<void(boost::system::error_code const &, size_t)> callback;
	};
	size_t const queue_size_max = 64 * 1024;

	oslo::ipc::ipc_server & server;
	oslo::node & node;

	/** Unique session id */
	std::atomic<uint64_t> session_id;

	/** Service name associated with this session. This is set through the ServiceRegister API */
	oslo::locked<std::string> service_name;

	/**
	 * The payload encoding currently in use by this session. This is set as requests are
	 * received and usually never changes (although a client technically can)
	 */
	std::atomic<oslo::ipc::payload_encoding> active_encoding;

	/** Timer for measuring the duration of ipc calls */
	oslo::timer<std::chrono::microseconds> session_timer;

	/**
	 * IO context from node, or per-transport, depending on configuration.
	 * Certain transports may scale better if they use a separate context.
	 */
	boost::asio::io_context & io_ctx;

	/** IO strand for synchronizing */
	boost::asio::strand<boost::asio::io_context::executor_type> strand;

	/** The send queue is protected by always being accessed through the strand */
	std::deque<queue_item> send_queue;

	/** A socket of the given asio type */
	SOCKET_TYPE socket;

	/** Buffer sizes are read into this */
	uint32_t buffer_size{ 0 };

	/** Buffer used to store data received from the client */
	std::vector<uint8_t> buffer;

	/** Transport configuration */
	oslo::ipc::ipc_config_transport & config_transport;

	/** Handler for Flatbuffers requests. This is created lazily on the first request. */
	std::shared_ptr<oslo::ipc::flatbuffers_handler> flatbuffers_handler;

	/** Session subscriber */
	std::shared_ptr<oslo::ipc::subscriber> subscriber;
};

/** Domain and TCP socket transport */
template <typename ACCEPTOR_TYPE, typename SOCKET_TYPE, typename ENDPOINT_TYPE>
class socket_transport : public oslo::ipc::transport
{
public:
	socket_transport (oslo::ipc::ipc_server & server_a, ENDPOINT_TYPE endpoint_a, oslo::ipc::ipc_config_transport & config_transport_a, int concurrency_a) :
	server (server_a), config_transport (config_transport_a)
	{
		// Using a per-transport event dispatcher?
		if (concurrency_a > 0)
		{
			io_ctx = std::make_unique<boost::asio::io_context> ();
		}

		boost::asio::socket_base::reuse_address option (true);
		boost::asio::socket_base::keep_alive option_keepalive (true);
		acceptor = std::make_unique<ACCEPTOR_TYPE> (context (), endpoint_a);
		acceptor->set_option (option);
		acceptor->set_option (option_keepalive);
		accept ();

		// Start serving IO requests. If concurrency_a is < 1, the node's thread pool/io_context is used instead.
		// A separate io_context for domain sockets may facilitate better performance on some systems.
		if (concurrency_a > 0)
		{
			runner = std::make_unique<oslo::thread_runner> (*io_ctx, static_cast<unsigned> (concurrency_a));
		}
	}

	boost::asio::io_context & context () const
	{
		return io_ctx ? *io_ctx : server.node.io_ctx;
	}

	void accept ()
	{
		// Prepare the next session
		auto new_session (std::make_shared<session<SOCKET_TYPE>> (server, context (), config_transport));

		acceptor->async_accept (new_session->get_socket (), [this, new_session](boost::system::error_code const & ec) {
			if (!ec)
			{
				new_session->read_next_request ();
			}
			else
			{
				server.node.logger.always_log ("IPC: acceptor error: ", ec.message ());
			}

			if (ec != boost::asio::error::operation_aborted && acceptor->is_open ())
			{
				this->accept ();
			}
			else
			{
				server.node.logger.always_log ("IPC: shutting down");
			}
		});
	}

	void stop ()
	{
		acceptor->close ();
		if (io_ctx)
		{
			io_ctx->stop ();
		}

		if (runner)
		{
			runner->join ();
		}
	}

private:
	oslo::ipc::ipc_server & server;
	oslo::ipc::ipc_config_transport & config_transport;
	std::unique_ptr<oslo::thread_runner> runner;
	std::unique_ptr<boost::asio::io_context> io_ctx;
	std::unique_ptr<ACCEPTOR_TYPE> acceptor;
};
}

/**
 * Awaits SIGHUP via signal_set instead of std::signal, as this allows the handler to escape the
 * Posix signal handler restrictions
 */
void await_hup_signal (std::shared_ptr<boost::asio::signal_set> const & signals, oslo::ipc::ipc_server & server_a)
{
	signals->async_wait ([signals, &server_a](const boost::system::error_code & ec, int signal_number) {
		if (ec != boost::asio::error::operation_aborted)
		{
			std::cout << "Reloading access configuration..." << std::endl;
			auto error (server_a.reload_access_config ());
			if (!error)
			{
				std::cout << "Reloaded access configuration successfully" << std::endl;
			}
			await_hup_signal (signals, server_a);
		}
	});
}

oslo::ipc::ipc_server::ipc_server (oslo::node & node_a, oslo::node_rpc_config const & node_rpc_config_a) :
node (node_a),
node_rpc_config (node_rpc_config_a),
broker (node_a)
{
	try
	{
		oslo::error access_config_error (reload_access_config ());
		if (access_config_error)
		{
			std::exit (1);
		}
#ifndef _WIN32
		// Hook up config reloading through the HUP signal
		auto signals (std::make_shared<boost::asio::signal_set> (node.io_ctx, SIGHUP));
		await_hup_signal (signals, *this);
#endif
		if (node_a.config.ipc_config.transport_domain.enabled)
		{
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
			auto threads = node_a.config.ipc_config.transport_domain.io_threads;
			file_remover = std::make_unique<dsock_file_remover> (node_a.config.ipc_config.transport_domain.path);
			boost::asio::local::stream_protocol::endpoint ep{ node_a.config.ipc_config.transport_domain.path };
			transports.push_back (std::make_shared<socket_transport<boost::asio::local::stream_protocol::acceptor, boost::asio::local::stream_protocol::socket, boost::asio::local::stream_protocol::endpoint>> (*this, ep, node_a.config.ipc_config.transport_domain, threads));
#else
			node.logger.always_log ("IPC: Domain sockets are not supported on this platform");
#endif
		}

		if (node_a.config.ipc_config.transport_tcp.enabled)
		{
			auto threads = node_a.config.ipc_config.transport_tcp.io_threads;
			transports.push_back (std::make_shared<socket_transport<boost::asio::ip::tcp::acceptor, boost::asio::ip::tcp::socket, boost::asio::ip::tcp::endpoint>> (*this, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v6 (), node_a.config.ipc_config.transport_tcp.port), node_a.config.ipc_config.transport_tcp, threads));
		}

		node.logger.always_log ("IPC: server started");

		if (!transports.empty ())
		{
			broker.start ();
		}
	}
	catch (std::runtime_error const & ex)
	{
		node.logger.always_log ("IPC: ", ex.what ());
	}
}

oslo::ipc::ipc_server::~ipc_server ()
{
	node.logger.always_log ("IPC: server stopped");
}

void oslo::ipc::ipc_server::stop ()
{
	for (auto & transport : transports)
	{
		transport->stop ();
	}
}

oslo::ipc::broker & oslo::ipc::ipc_server::get_broker ()
{
	return broker;
}

oslo::ipc::access & oslo::ipc::ipc_server::get_access ()
{
	return access;
}

oslo::error oslo::ipc::ipc_server::reload_access_config ()
{
	oslo::error access_config_error (oslo::ipc::read_access_config_toml (node.application_path, access));
	if (access_config_error)
	{
		auto error (boost::str (boost::format ("IPC: invalid access configuration file: %1%") % access_config_error.get_message ()));
		std::cerr << error << std::endl;
		node.logger.always_log (error);
	}
	return access_config_error;
}

ext: cpp

max_stars_repo_name: oslocurrency/oslo-node

max_issues_repo_name: oslocurrency/oslo-node

max_forks_repo_name: oslocurrency/oslo-node


text:
#include "StdAfx.h"
#include "ComRecord.h"
#include "record_local.h"
#include "miscwrappers.h"

#include <boost/test/unit_test.hpp>
#ifdef UNIT_TEST
BOOST_AUTO_TEST_SUITE( TestComRecord )

	using namespace mem_engine ;

	typedef CComPtr< CComObject< CRecord > > com_rec_ptr ;

	BOOST_AUTO_TEST_CASE( Instantiate )
	{
		com_rec_ptr rec ;
		HRESULT hr = CComObject< CRecord >::CreateInstance( &rec ) ;
		BOOST_CHECK( SUCCEEDED( hr ) ) ;
		BOOST_CHECK( rec ) ;
	}
	// trans
	BOOST_AUTO_TEST_CASE( trans_empty )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR result ;
		rec->get_Trans(&result) ;
		BOOST_CHECK_EQUAL("", string(CW2A(result))) ;
	}
	BOOST_AUTO_TEST_CASE( trans )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR trans = L"spam" ;
		rec->put_Trans(trans) ;
		CComBSTR result ;
		rec->get_Trans(&result) ;
		BOOST_CHECK_EQUAL("spam", string(CW2A(result))) ;
	}
	BOOST_AUTO_TEST_CASE( trans_plain )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR trans = L"spam & eggs" ;
		rec->put_Trans(trans) ;
		CComBSTR result ;
		rec->get_PlainTrans(&result) ;
		BOOST_CHECK_EQUAL("spam & eggs", string(CW2A(result))) ;
	}

	// source
	BOOST_AUTO_TEST_CASE( source )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR source = L"spam" ;
		rec->put_Source(source) ;
		CComBSTR result ;
		rec->get_Source(&result) ;
		BOOST_CHECK_EQUAL("spam", string(CW2A(result))) ;
	}
	BOOST_AUTO_TEST_CASE( source_rich )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR source = L"spam" ;
		rec->put_Source(source) ;
		CComBSTR result ;
		rec->get_Source(&result) ;
		BOOST_CHECK_EQUAL("spam", string(CW2A(result))) ;
	}
	BOOST_AUTO_TEST_CASE( source_plain )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR source = L"spam" ;
		rec->put_Source(source) ;
		CComBSTR result ;
		rec->get_PlainSource(&result) ;
		BOOST_CHECK_EQUAL("spam", string(CW2A(result))) ;
	}

	BOOST_AUTO_TEST_CASE( source_empty )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR result ;
		rec->get_Source(&result) ;
		BOOST_CHECK_EQUAL("", string(CW2A(result))) ;
	}
	// context
	BOOST_AUTO_TEST_CASE( context )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR context = L"context" ;
		rec->put_Context(context) ;
		CComBSTR result ;
		rec->get_Context(&result) ;
		BOOST_CHECK_EQUAL("context", string(CW2A(result))) ;
	}
	BOOST_AUTO_TEST_CASE( context_plain )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR context = L"
context

" ;
		rec->put_Context(context) ;
		CComBSTR result ;
		rec->get_PlainContext(&result) ;
		BOOST_CHECK_EQUAL("context", string(CW2A(result))) ;
	}
	// created by
	BOOST_AUTO_TEST_CASE( created_by )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR creator = L"creator" ;
		rec->put_CreatedBy(creator) ;
		CComBSTR result ;
		rec->get_CreatedBy(&result) ;
		BOOST_CHECK_EQUAL("creator", string(CW2A(result))) ;
	}
	// modified by
	BOOST_AUTO_TEST_CASE( modified_by )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		CComBSTR modified_by = L"modified_by" ;
		rec->put_ModifiedBy(modified_by) ;
		CComBSTR result ;
		rec->get_ModifiedBy(&result) ;
		BOOST_CHECK_EQUAL("modified_by", string(CW2A(result))) ;
	}
	BOOST_AUTO_TEST_CASE( modified_by_changes_record )
	{
		record_pointer record(new record_local) ;
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		rec->set_record(record) ;
		CComBSTR modified_by = L"modified_by" ;
		rec->put_ModifiedBy(modified_by) ;
		BOOST_CHECK_EQUAL("modified_by", string(string2string(record->get_modified_by()).c_str())) ;
	}
	// refcount
	BOOST_AUTO_TEST_CASE( get_refcount )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		rec->put_RefCount(10) ;
		ULONG result(0);
		rec->get_RefCount(&result) ;
		BOOST_CHECK_EQUAL(10u, result) ;
	}
	// date created
	BOOST_AUTO_TEST_CASE( get_created )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;

		record_pointer record(new record_local) ;
		rec->set_record(record) ;
		misc_wrappers::date created ;
		created.set_to_local_time() ;
		created.wYear = 2005 ;
		created.wMonth = 7 ;
		created.wDay = 10 ;
		record->set_created(created) ;

		DATE result(0);
		rec->get_DateCreated(&result) ;

		SYSTEMTIME rectime ;
		::VariantTimeToSystemTime(result, &rectime) ;
		BOOST_CHECK_EQUAL(2005, rectime.wYear) ;
		BOOST_CHECK_EQUAL(7, rectime.wMonth) ;
	}

	BOOST_AUTO_TEST_CASE( set_created )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;

		record_pointer record(new record_local) ;
		rec->set_record(record) ;
		misc_wrappers::date created ;
		created.set_to_local_time() ;
		created.wYear = 2003 ;
		created.wMonth = 6 ;
		created.wDay = 10 ;

		DATE setting(0);
		::SystemTimeToVariantTime(&created, &setting) ;

		rec->put_DateCreated(setting) ;

		misc_wrappers::date result = record->get_created() ;

		BOOST_CHECK_EQUAL(2003, result.wYear) ;
		BOOST_CHECK_EQUAL(6, result.wMonth) ;
		BOOST_CHECK_EQUAL(10, result.wDay) ;
	}

	// date modified
	BOOST_AUTO_TEST_CASE( get_modified )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;

		record_pointer record(new record_local) ;
		rec->set_record(record) ;
		misc_wrappers::date modified ;
		modified.set_to_local_time() ;
		modified.wYear = 2005 ;
		modified.wMonth = 7 ;
		record->set_modified(modified) ;

		DATE result(0);
		rec->get_LastModified(&result) ;

		SYSTEMTIME rectime ;
		::VariantTimeToSystemTime(result, &rectime) ;
		BOOST_CHECK_EQUAL(2005, rectime.wYear) ;
		BOOST_CHECK_EQUAL(7, rectime.wMonth) ;
	}

	BOOST_AUTO_TEST_CASE( set_modified )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;

		record_pointer record(new record_local) ;
		rec->set_record(record) ;
		misc_wrappers::date modified ;
		modified.set_to_local_time() ;
		modified.wYear = 2003 ;
		modified.wMonth = 2 ;
		modified.wDay = 10 ;

		DATE setting(0);
		::SystemTimeToVariantTime(&modified, &setting) ;

		rec->put_LastModified(setting) ;

		misc_wrappers::date result = record->get_modified() ;

		BOOST_CHECK_EQUAL(2003, result.wYear) ;
		BOOST_CHECK_EQUAL(2, result.wMonth) ;
	}

	// id
	BOOST_AUTO_TEST_CASE( get_id_0 )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		ULONG result = 10;
		rec->get_Id(&result) ;
		BOOST_CHECK_EQUAL(0u, result) ;
	}
	BOOST_AUTO_TEST_CASE( set_id )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		rec->put_Id(10) ;
		ULONG result = 0;
		rec->get_Id(&result) ;
		BOOST_CHECK_EQUAL(10u, result) ;
	}

	// reliability
	BOOST_AUTO_TEST_CASE( get_reliability_0 )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		ULONG result = 10;
		rec->get_Reliability(&result) ;
		BOOST_CHECK_EQUAL(0u, result) ;
	}
	BOOST_AUTO_TEST_CASE( set_reliability )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		rec->put_Reliability(5u) ;
		ULONG result = 0;
		rec->get_Reliability(&result) ;
		BOOST_CHECK_EQUAL(5u, result) ;
	}
	// validated
	BOOST_AUTO_TEST_CASE(get_validated_inits_to_false)
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		VARIANT_BOOL result = VARIANT_TRUE;
		rec->get_Validated(&result) ;
		BOOST_CHECK_EQUAL((int)VARIANT_FALSE, (int)result) ;
	}
	BOOST_AUTO_TEST_CASE( set_validated )
	{
		com_rec_ptr rec ;
		CComObject< CRecord >::CreateInstance( &rec ) ;
		rec->put_Validated(VARIANT_TRUE) ;
		VARIANT_BOOL result = VARIANT_FALSE;
		rec->get_Validated(&result) ;
		BOOST_CHECK_EQUAL((int)VARIANT_TRUE, (int)result) ;
	}
BOOST_AUTO_TEST_SUITE_END()

//////////////////////////////////////////////////////////////////////////
// comrec2rec
//////////////////////////////////////////////////////////////////////////

BOOST_AUTO_TEST_SUITE( TestComRecord2Record )

	using namespace mem_engine ;

	typedef CComObject<CRecord> rec_obj ;

	struct ComRec
	{
		rec_obj *rec ;
		CComPtr<IRecord> comrec ;
		ComRec()
		{
			rec_obj::CreateInstance(&rec) ;
			rec->AddRef() ;
			rec->QueryInterface(&comrec) ;
		}
		~ComRec()
		{
			rec->Release() ;
		}
	};

	// source
	BOOST_AUTO_TEST_CASE( copy_source )
	{
		ComRec rec ;

		CComBSTR val = L"foo" ;
		rec.comrec->put_Source(val) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(L"foo", localrec->get_source_rich()) ;
	}

	// trans
	BOOST_AUTO_TEST_CASE( copy_trans )
	{
		ComRec rec ;

		CComBSTR val = L"foo" ;
		rec.comrec->put_Trans(val) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(L"foo", localrec->get_trans_rich()) ;
	}

	// context
	BOOST_AUTO_TEST_CASE( copy_context )
	{
		ComRec rec ;

		CComBSTR val = L"foo" ;
		rec.comrec->put_Context(val) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(L"foo", localrec->get_context_rich()) ;
	}

	// validated
	BOOST_AUTO_TEST_CASE(copy_validated_false)
	{
		ComRec rec ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(false, localrec->is_validated()) ;
	}
	BOOST_AUTO_TEST_CASE(copy_validated_true)
	{
		ComRec rec ;

		rec.comrec->put_Validated(VARIANT_TRUE) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(true, localrec->is_validated()) ;
	}

	// reliability
	BOOST_AUTO_TEST_CASE(copy_reliability)
	{
		ComRec rec ;

		rec.comrec->put_Reliability(15u) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(9u, localrec->get_reliability()) ;
	}

	// refcount
	BOOST_AUTO_TEST_CASE(copy_refcount)
	{
		ComRec rec ;

		rec.comrec->put_RefCount(15u) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(15u, localrec->get_refcount()) ;
	}

	// id
	BOOST_AUTO_TEST_CASE(copy_id)
	{
		ComRec rec ;

		rec.comrec->put_Id(1u) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(1u, localrec->get_id()) ;
	}

	// created_by
	BOOST_AUTO_TEST_CASE(copy_creator)
	{
		ComRec rec ;

		rec.comrec->put_CreatedBy(CComBSTR(L"Chuck")) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(L"Chuck", localrec->get_creator()) ;
	}

	// modified_by
	BOOST_AUTO_TEST_CASE(copy_modified_by)
	{
		ComRec rec ;

		rec.comrec->put_ModifiedBy(CComBSTR(L"Chuck")) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(L"Chuck", localrec->get_modified_by()) ;
	}

	// created
	BOOST_AUTO_TEST_CASE(copy_created)
	{
		ComRec rec ;
		misc_wrappers::date created;
		created.set_to_local_time() ;
		rec.rec->m_record->set_created(created) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(created.wYear, localrec->get_created().wYear) ;
		BOOST_CHECK_EQUAL(created.wMonth, localrec->get_created().wMonth) ;
		BOOST_CHECK_EQUAL(created.wDay, localrec->get_created().wDay) ;
	}

	// modified
	BOOST_AUTO_TEST_CASE(copy_modified)
	{
		ComRec rec ;
		misc_wrappers::date modified;
		modified.set_to_local_time() ;
		rec.rec->m_record->set_modified(modified) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(modified.wYear, localrec->get_modified().wYear) ;
		BOOST_CHECK_EQUAL(modified.wMonth, localrec->get_modified().wMonth) ;
		BOOST_CHECK_EQUAL(modified.wDay, localrec->get_modified().wDay) ;
	}

	// multiple
	BOOST_AUTO_TEST_CASE( copy_multiple )
	{
		ComRec rec ;

		rec.comrec->put_Source(CComBSTR(L"source")) ;
		rec.comrec->put_Trans(CComBSTR(L"trans")) ;
		rec.comrec->put_Context(CComBSTR(L"context")) ;
		rec.comrec->put_Reliability(7u) ;
		rec.comrec->put_RefCount(10u) ;

		record_pointer localrec = comrec2rec(rec.comrec);
		BOOST_CHECK_EQUAL(L"source", localrec->get_source_rich()) ;
		BOOST_CHECK_EQUAL(L"trans", localrec->get_trans_rich()) ;
		BOOST_CHECK_EQUAL(L"context", localrec->get_context_rich()) ;
		BOOST_CHECK_EQUAL(7u, localrec->get_reliability()) ;
		BOOST_CHECK_EQUAL(10u, localrec->get_refcount()) ;
	}

BOOST_AUTO_TEST_SUITE_END()
#endif

max_stars_repo_name: ultimatezen/felix

max_issues_repo_name: ultimatezen/felix

max_forks_repo_name: ultimatezen/felix


text: #include <boost/spirit/home/classic/meta.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#pragma once

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>

#include <boost/functional/hash.hpp>

#include <common/traits.hpp>
#include <common/types.hpp>

namespace vitamine
{
	template <typename T, typename Tag = void>
	struct Vector2XZ
	{
		using ComponentType = T;

		T x, z;

		Vector2XZ() noexcept = default;
		constexpr Vector2XZ(T x, T z) noexcept : x(x), z(z) {}

		[[nodiscard]]
		bool withinOrdered(Vector2XZ from, Vector2XZ to) const
		{
			assert(from.x <= to.x);
			assert(from.z <= to.z);
			return x >= from.x && x <= to.x
			    && z >= from.z && z <= to.z;
		}

		template <typename U = T>
		[[nodiscard]]
		constexpr T lengthSquared() const
		{
			auto x = static_cast<U>(this->x);
			auto z = static_cast<U>(this->z);
			return x * x + z * z;
		}

		template <typename F = Float64>
		[[nodiscard]]
		F length() const
		{
			using std::sqrt;
			return sqrt(static_cast<F>(lengthSquared()));
		}
	};

	template <typename T, typename Tag = void>
	struct Vector3XYZ
	{
		using ComponentType = T;

		T x, y, z;

		Vector3XYZ() noexcept = default;
		constexpr Vector3XYZ(T x, T y, T z) noexcept : x(x), y(y), z(z) {}

		[[nodiscard]]
		bool withinOrdered(Vector3XYZ from, Vector3XYZ to)
		{
			assert(from.x <= to.x);
			assert(from.y <= to.y);
			assert(from.z <= to.z);
			return x >= from.x && x <= to.x
			    && y >= from.y && y <= to.y
			    && z >= from.z && z <= to.z;
		}

		template <typename U = T>
		[[nodiscard]]
		constexpr T lengthSquared() const
		{
			auto x = static_cast<U>(this->x);
			auto y = static_cast<U>(this->y);
			auto z = static_cast<U>(this->z);
			return x * x + y * y + z * z;
		}

		template <typename F = Float64>
		[[nodiscard]]
		F length() const
		{
			using std::sqrt;
			return sqrt(static_cast<F>(lengthSquared()));
		}
	};

	static_assert(std::is_trivial_v<Vector2XZ <Int>>);
	static_assert(std::is_trivial_v<Vector3XYZ<Int>>);

	static_assert(sizeof(Vector2XZ <Int>) == 2 * sizeof(Int));
	static_assert(sizeof(Vector3XYZ<Int>) == 3 * sizeof(Int));

	template <typename T, typename Tag>
	constexpr bool operator==(Vector2XZ<T, Tag> a, Vector2XZ<T, Tag> b)
	{
		return a.x == b.x && a.z == b.z;
	}

	template <typename T, typename Tag>
	constexpr bool operator==(Vector3XYZ<T, Tag> a, Vector3XYZ<T, Tag> b)
	{
		return a.x == b.x && a.y == b.y && a.z == b.z;
	}

	template <typename T, typename Tag>
	constexpr bool operator!=(Vector2XZ<T, Tag> a, Vector2XZ<T, Tag> b)
	{
		return !(a == b);
	}

	template <typename T, typename Tag>
	constexpr bool operator!=(Vector3XYZ<T, Tag> a, Vector3XYZ<T, Tag> b)
	{
		return !(a == b);
	}

	template <typename T, typename Tag>
	constexpr Vector2XZ<T, Tag>& operator+=(Vector2XZ<T, Tag>& a, Vector2XZ<T, Tag> b)
	{
		a.x += b.x;
		a.z += b.z;
		return a;
	}

	template <typename T, typename Tag>
	constexpr Vector3XYZ<T, Tag>& operator+=(Vector3XYZ<T, Tag>& a, Vector3XYZ<T, Tag> b)
	{
		a.x += b.x;
		a.y += b.y;
		a.z += b.z;
		return a;
	}

	template <typename T, typename Tag>
	constexpr Vector2XZ<T, Tag>& operator-=(Vector2XZ<T, Tag>& a, Vector2XZ<T, Tag> b)
	{
		a.x -= b.x;
		a.z -= b.z;
		return a;
	}

	template <typename T, typename Tag>
	constexpr Vector3XYZ<T, Tag>& operator-=(Vector3XYZ<T, Tag>& a, Vector3XYZ<T, Tag> b)
	{
		a.x -= b.x;
		a.y -= b.y;
		a.z -= b.z;
		return a;
	}

	template <typename T, typename Tag>
	constexpr Vector2XZ<T, Tag> operator+(Vector2XZ<T, Tag> a, Vector2XZ<T, Tag> b)
	{
		return {a.x + b.x, a.z + b.z};
	}

	template <typename T, typename Tag>
	constexpr Vector3XYZ<T, Tag> operator+(Vector3XYZ<T, Tag> a, Vector3XYZ<T, Tag> b)
	{
		return {a.x + b.x, a.y + b.y, a.z + b.z};
	}

	template <typename T, typename Tag>
	constexpr Vector2XZ<T, Tag> operator-(Vector2XZ<T, Tag> a, Vector2XZ<T, Tag> b)
	{
		return {a.x - b.x, a.z - b.z};
	}

	template <typename T, typename Tag>
	constexpr Vector3XYZ<T, Tag> operator-(Vector3XYZ<T, Tag> a, Vector3XYZ<T, Tag> b)
	{
		return {a.x - b.x, a.y - b.y, a.z - b.z};
	}

	template <typename T, typename Tag>
	constexpr Vector2XZ<T, Tag> operator*(Vector2XZ<T, Tag> v, typename Identity<T>::Type n)
	{
		return {v.x * n, v.z * n};
	}

	template <typename T, typename Tag>
	constexpr Vector3XYZ<T, Tag> operator*(Vector3XYZ<T, Tag> v, typename Identity<T>::Type n)
	{
		return {v.x * n, v.y * n, v.z * n};
	}

	template <typename T, typename Tag>
	constexpr Vector2XZ<T, Tag> operator*(typename Identity<T>::Type n, Vector2XZ<T, Tag> v)
	{
		return {n * v.x, n * v.z};
	}

	template <typename T, typename Tag>
	constexpr Vector3XYZ<T, Tag> operator*(typename Identity<T>::Type n, Vector3XYZ<T, Tag> v)
	{
		return {n * v.x, n * v.y, n * v.z};
	}

	template <typename T, typename Tag>
	constexpr Vector2XZ<T, Tag> operator/(Vector2XZ<T, Tag> v, typename Identity<T>::Type n)
	{
		return {v.x / n, v.z / n};
	}

	template <typename T, typename Tag>
	constexpr Vector3XYZ<T, Tag> operator/(Vector3XYZ<T, Tag> v, typename Identity<T>::Type n)
	{
		return {v.x / n, v.y / n, v.z / n};
	}

	template <typename T, typename Tag>
	constexpr Vector2XZ<T, Tag> operator/(typename Identity<T>::Type n, Vector2XZ<T, Tag> v)
	{
		return {n / v.x, n / v.z};
	}

	template <typename T, typename Tag>
	constexpr Vector3XYZ<T, Tag> operator/(typename Identity<T>::Type n, Vector3XYZ<T, Tag> v)
	{
		return {n / v.x, n / v.y, n / v.z};
	}

	template <typename T, typename Tag>
	std::string toString(Vector2XZ<T, Tag> v)
	{
		return '(' + std::to_string(v.x) + ',' + ' ' + std::to_string(v.z) + ')';
	}

	template <typename T, typename Tag>
	std::string toString(Vector3XYZ<T, Tag> v)
	{
		return '(' + std::to_string(v.x) + ',' + ' ' + std::to_string(v.y) + ',' + ' ' + std::to_string(v.z) + ')';
	}
}

namespace std
{
	template <typename T, typename Tag>
	struct hash<vitamine::Vector2XZ<T, Tag>>
	{
		std::size_t operator()(vitamine::Vector2XZ<T, Tag> v) const noexcept
		{
			return boost::hash_value(std::tie(v.x, v.z));
		}
	};

	template <typename T, typename Tag>
	struct hash<vitamine::Vector3XYZ<T, Tag>>
	{
		std::size_t operator()(vitamine::Vector3XYZ<T, Tag> v) const noexcept
		{
			return boost::hash_value(std::tie(v.x, v.y, v.z));
		}
	};

	template <typename T, typename Tag>
	struct less<vitamine::Vector2XZ<T, Tag>>
	{
		constexpr bool operator()(vitamine::Vector2XZ<T, Tag> a, vitamine::Vector2XZ<T, Tag> b) const noexcept
		{
			if(a.x < b.x)
				return true;

			if(a.x > b.x)
				return false;

			return a.z < b.z;
		}
	};

	template <typename T, typename Tag>
	struct less<vitamine::Vector3XYZ<T, Tag>>
	{
		constexpr bool operator()(vitamine::Vector3XYZ<T, Tag> a, vitamine::Vector3XYZ<T, Tag> b) const noexcept
		{
			if(a.x < b.x)
				return true;

			if(a.x > b.x)
				return false;

			if(a.y < b.y)
				return true;

			if(a.y > b.y)
				return false;

			return a.z < b.z;
		}
	};
}

max_stars_repo_name: mgrech/vitamine

max_issues_repo_name: mgrech/vitamine

max_forks_repo_name: mgrech/vitamine


text:
/*

Copyright (c) 2005-2022, University of Oxford.
All rights reserved.

University of Oxford means the Chancellor, Masters and Scholars of the
University of Oxford, having an administrative office at Wellington
Square, Oxford OX1 2JD, UK.

This file is part of Chaste.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 * Neither the name of the University of Oxford nor the names of its
   contributors may be used to endorse or promote products derived from this
   software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "Identifiable.hpp"

#include <algorithm>
#include <typeinfo>

#include <boost/serialization/extended_type_info.hpp>
#include <boost/serialization/extended_type_info_typeid.hpp>
#include <boost/serialization/extended_type_info_no_rtti.hpp>
#include <boost/serialization/type_info_implementation.hpp>
#include "Warnings.hpp"

std::string Identifiable::TidyTemplatedExportIdentifier(std::string identifier) const
{
    // First remove spaces, so identifier now takes the form "pack<void(NameOfDerivedType<DIM>)>::type"
    std::string::iterator end_pos = std::remove(identifier.begin(), identifier.end(), ' ');
    identifier.erase(end_pos, identifier.end());

    // Then remove "pack<void(", so identifier now takes the form "NameOfDerivedType<DIM>)>::type"
    const std::string s_pack = "pack<void(";
    std::string::size_type i = identifier.find(s_pack);
    if (i != identifier.npos)
    {
        identifier.erase(i, s_pack.length());
    }

    // Then replace "<" with "-", so identifier now takes the form "NameOfDerivedType-DIM>)>::type"
    const std::string s_open = "<";
    const std::string s_dash = "-";
    i = identifier.find(s_open);
    if (i != identifier.npos)
    {
        identifier.replace(i, s_open.length(), s_dash);
    }

    // Then replace "," with "-" to account for multiple template parameters
    const std::string s_comma = ",";
    i = identifier.find(s_comma);
    while (i != identifier.npos)
    {
        identifier.replace(i, s_comma.length(), s_dash);
        i = identifier.find(s_comma, i);
    }

    // Finally remove ">)>::type", so that identifier now takes the form "NameOfDerivedType-DIM"
    const std::string s_end = ">)>::type";
    i = identifier.find(s_end);
    if (i != identifier.npos)
    {
        identifier.erase(i, s_end.length());
    }

    return identifier;
}

Identifiable::~Identifiable()
{
}

std::string Identifiable::GetIdentifier() const
{
    std::string id;
#if BOOST_VERSION >= 103700
    const boost::serialization::extended_type_info* p_type_info =
            boost::serialization::type_info_implementation<Identifiable>::type::get_const_instance().get_derived_extended_type_info(*this);
    if(p_type_info!=nullptr)
    {
        id = p_type_info->get_key();
    }
    else
    {
        WARN_ONCE_ONLY("Unable to determine the class type. If you are using C++ serialization may not be set up correctly. \n If you are using Python this behaviour is expected.");
        id = "UnknownClass-ReflectionFailed";
    }
#else
    id = boost::serialization::type_info_implementation<Identifiable>::type::get_derived_extended_type_info(*this)->get_key();
#endif
    return TidyTemplatedExportIdentifier(id);
}

max_stars_repo_name: stu-l/Chaste

max_issues_repo_name: stu-l/Chaste

max_forks_repo_name: stu-l/Chaste


text:
#define BOOST_TEST_MODULE cnnefTestMarray

#include <boost/test/unit_test.hpp>

#include <iostream>

#include "cnnef/tools/runtime_check.hxx"
#include "cnnef/marray/marray.hxx"

BOOST_AUTO_TEST_CASE(StridesTest)
{
    std::vector<size_t> shape({10,20});
    cnnef::marray::Marray<int> a(shape.begin(), shape.end());
    CNNEF_TEST_OP(a.strides(1),==,1);
    CNNEF_TEST_OP(a.strides(0),==,20);
}

ext: cxx

max_stars_repo_name: DerThorsten/cnnef

max_issues_repo_name: DerThorsten/cnnef

max_forks_repo_name: DerThorsten/cnnef


text:
#include "PointAnyverse.h"
#include <pcl/io/pcd_io.h>
#include <iostream>
#include <ros/ros.h>
#include <boost/filesystem.hpp>
#include <vector>
#include <algorithm>
#include "alphanum.h"
#include "HelperRosRelated.h"

int main(int argc, char **argv) {
  ros::init(argc, argv, "anyverse_cloud_viewer_node");
  ros::NodeHandle nh("~");

  std::string path_folder;
  nh.getParam("path_lidar_point_cloud", path_folder);

  ros::Publisher pub_cloud = nh.advertise<sensor_msgs::PointCloud2>(
    "/cloud_anyverse", 1);

  using namespace boost::filesystem;

  if (!is_directory(path_folder)) {
    std::cout << path_folder << " is not a directory." << std::endl;
    return -1;
  }

  std::vector<path> vec_unordered_dirs;
  std::copy(directory_iterator(path_folder), directory_iterator(), std::back_inserter(vec_unordered_dirs));

  std::vector<std::string> vec_ordered_dirs;
  std::transform(vec_unordered_dirs.begin(), vec_unordered_dirs.end(), std::back_inserter(vec_ordered_dirs),
                 [](const path &c) -> std::string { return c.string(); });

  std::sort(vec_ordered_dirs.begin(), vec_ordered_dirs.end(), doj::alphanum_less<std::string>());

  // print pcd file paths to be read
  std::cout << path_folder << " is a directory containing:" << std::endl;
  for (std::vector<std::string>::const_iterator it(vec_ordered_dirs.begin()); it != vec_ordered_dirs.end(); ++it) {
    std::cout << "   " << *it << '\n';
  }

  // publishing rate
  ros::Rate rate(10);

  for (const auto &path : vec_ordered_dirs) {
    // read with custom point format
    using CloudAnyverse = pcl::PointCloud<PointAnyverse>;
    CloudAnyverse::Ptr cloud_anyverse(new CloudAnyverse);

    if (pcl::io::loadPCDFile<PointAnyverse>(path, *cloud_anyverse) == -1) {
      PCL_ERROR ("Couldn't read file test_pcd.pcd \n");
      return (-1);
    }

    using PointRGB = pcl::PointXYZRGB;
    using CloudRGB = pcl::PointCloud<PointRGB>;

    // convert it into standard pcl::PointXYZRGB
    CloudRGB::Ptr cloud_rgb(new CloudRGB);
    std::transform(cloud_anyverse->points.begin(), cloud_anyverse->points.end(), std::back_inserter(cloud_rgb->points),
                   [](const PointAnyverse &p) -> PointRGB {
                     PointRGB point;
                     point.x = p.x;
//                     point.y = p.y;
//                     point.z = p.z;
                     point.y = p.z; // dirty axis fix
                     point.z = p.y; // dirty axis fix
                     point.r = p.r0;
                     point.g = p.g0;
                     point.b = p.b0;
                     return point;
                   });

    HelperRosRelated::PublishCloud<pcl::PointXYZRGB>(*cloud_rgb, pub_cloud, ros::Time::now(), "base_link");
    ros::spinOnce();
    rate.sleep();
  }
  return 0;
}


text:
#include <iostream>
#include <thread> // for ioservice thread
#include <string.h> // for memchr

#include <boost/asio.hpp>
#include <boost/asio.hpp>
#include <boost/asio/read.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/optional.hpp>

#if defined(__linux__)
#include <linux/serial.h>
#endif

#include <misc.hpp>

// OBS! You can change between async_read and async_read_some depending on whether to block
// and wait for the buffer to be filled up or run the callback with whatever data
// that is available at the time of reading
// See https://stackoverflow.com/a/28509826

// Serial port
boost::asio::io_service ioservice;
boost::asio::serial_port port = boost::asio::serial_port(ioservice);
std::thread ioservice_thread;
const bool hwflow{false};
std::array<uint8_t, 15> read_buffer;

void ProcessIncomingBytes(uint8_t * buffer, size_t bytes_received);

void ReadCallback(const boost::system::error_code &error, std::size_t bytes_transferred)
{
    if (error == boost::system::errc::operation_canceled || error == boost::asio::error::eof) {
        // EOF error
        //port.async_read_some(boost::asio::buffer(read_buffer),
        //                      std::bind(&ReadCallback, std::placeholders::_1, std::placeholders::_2));
        boost::asio::async_read(port, boost::asio::buffer(read_buffer),
                                std::bind(&ReadCallback, std::placeholders::_1, std::placeholders::_2));
        return;
    } else if (error) {
        //throw std::runtime_error("serial asio: " + error.message());
        std::cout << "Serial Callback error: " << error.message() << std::endl;
    }

    ProcessIncomingBytes(&read_buffer[0], bytes_transferred);

    // READ THE NEXT PACKET
    //port.async_read_some(boost::asio::buffer(read_buffer),
    //                      std::bind(&ReadCallback, std::placeholders::_1, std::placeholders::_2));
    boost::asio::async_read(port, boost::asio::buffer(read_buffer),
                            std::bind(&ReadCallback, std::placeholders::_1, std::placeholders::_2));

    return;
}

void WriteCallback(const boost::system::error_code &error, size_t bytes_transferred) {
}

void Connect(std::string port_name, uint32_t baud_rate)
{
    // From https://github.com/mavlink/mavros/blob/master/libmavconn/src/serial.cpp
    try {
        port.open(port_name);

        // Set baudrate and 8N1 mode
        port.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
        port.set_option(boost::asio::serial_port_base::character_size(8));
        port.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
        port.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));

#if BOOST_ASIO_VERSION >= 101200 || !defined(__linux__)
        // Flow control setting in older versions of Boost.ASIO is broken, use workaround (below) for now.
        serial_dev.set_option(SPB::flow_control( (hwflow) ? SPB::flow_control::hardware : SPB::flow_control::none));
#elif BOOST_ASIO_VERSION < 101200 && defined(__linux__)
        // Workaround to set some options for the port manually. This is done in
        // Boost.ASIO, but until v1.12.0 (Boost 1.66) there was a bug which doesn't enable relevant
        // code. Fixed by commit: https://github.com/boostorg/asio/commit/619cea4356
        {
            int fd = port.native_handle();

            termios tio;
            tcgetattr(fd, &tio);

            // Set hardware flow control settings
            if (hwflow) {
                tio.c_iflag &= ~(IXOFF | IXON);
                tio.c_cflag |= CRTSCTS;
            } else {
                tio.c_iflag &= ~(IXOFF | IXON);
                tio.c_cflag &= ~CRTSCTS;
            }

            // Set serial port to "raw" mode to prevent EOF exit.
            cfmakeraw(&tio);

            // Commit settings
            tcsetattr(fd, TCSANOW, &tio);
        }
#endif

#if defined(__linux__)
        // Enable low latency mode on Linux
        {
            int fd = port.native_handle();

            struct serial_struct ser_info;
            ioctl(fd, TIOCGSERIAL, &ser_info);

            ser_info.flags |= ASYNC_LOW_LATENCY;

            ioctl(fd, TIOCSSERIAL, &ser_info);
        }
#endif
    }
    catch (boost::system::system_error &err) {
        //throw std::runtime_error("serial" + std::string(err.what()));
        std::cout << "Error: " << std::string(err.what()) << std::endl;
        exit(-1);
    }

    //port.async_read_some(boost::asio::buffer(read_buffer),
    //                     std::bind(&ReadCallback, std::placeholders::_1, std::placeholders::_2));
    boost::asio::async_read(port, boost::asio::buffer(read_buffer),
                        std::bind(&ReadCallback, std::placeholders::_1, std::placeholders::_2));
    // Start the I/O service in its own thread.
    ioservice_thread = std::thread([&] { ioservice.run(); });

    // Wait for start
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

void Disconnect()
{
    ioservice.stop();

    if (ioservice_thread.joinable()) {
        ioservice_thread.join();
    }

    try {
        port.close();
    }
    catch (boost::system::system_error &err) {
        //throw std::runtime_error("serial" + std::string(err.what()));
        std::cout << "Error: " << std::string(err.what()) << std::endl;
        exit(-1);
    }
}

template <typename SyncReadStream, typename MutableBufferSequence>
void readWithTimeout(SyncReadStream& s, const MutableBufferSequence& buffers, const boost::asio::deadline_timer::duration_type& expiry_time)
{
    boost::optional<boost::system::error_code> timer_result;
    boost::asio::deadline_timer timer(s.get_io_service());
    timer.expires_from_now(expiry_time);
    timer.async_wait([&timer_result] (const boost::system::error_code& error) { timer_result.reset(error); });

    boost::optional<boost::system::error_code> read_result;
    boost::asio::async_read(s, buffers, [&read_result] (const boost::system::error_code& error, size_t) { read_result.reset(error); });

    s.get_io_service().reset();
    while (s.get_io_service().run_one())
    {
        if (read_result)
            timer.cancel();
        else if (timer_result)
            s.cancel();
    }
    s.get_io_service().reset();

    if (*read_result)
        throw boost::system::system_error(*read_result);
}

boost::system::error_code Flush() {
    // From http://mnb.ociweb.com/mnb/MiddlewareNewsBrief-201303.html
#if 0
    boost::system::error_code ec;
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
    const bool isFlushed =! ::tcflush(controller_port.native(), TCIOFLUSH);
    if (!isFlushed)
        ec = boost::system::error_code(errno,
                                       boost::asio::error::get_system_category());
#else
    const bool isFlushed = ::PurgeComm(port.native(),
    PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR);
if (!isFlushed)
    ec = boost::system::error_code(::GetLastError(),
        boost::asio::error::get_system_category());
#endif
    return ec;
#else
    bool continueReading = true;
    while (continueReading) {
        try
        {
            readWithTimeout(port, boost::asio::buffer(read_buffer), boost::posix_time::milliseconds(1));
        }
        catch (boost::system::system_error& e)
        {
            continueReading = false;
        }
    }
#endif
}

bool isOpen() {
    return port.is_open();
}

void send(std::vector<uint8_t> buffer) {
    // Consider adding a mutex
    boost::asio::async_write(
            port, boost::asio::buffer(buffer),
            std::bind(&WriteCallback, std::placeholders::_1,
                      std::placeholders::_2));
}

// Should exit signals
EventSignal exit_signal;
void exitHandler(int s) {
    std::cout << "Exiting..." << std::endl;
    //should_exit = true;
    exit_signal.trigger();
}

int main(int argc, char* argv[])
{
    signal(SIGINT, exitHandler);

    Connect("/dev/ttyUSB0", 19200);
    exit_signal.waitForEvent();
    Disconnect();
}

void ProcessIncomingBytes(uint8_t * buffer, size_t bytes_received)
{
    uint8_t * start = (uint8_t*)memchr((void*)buffer, 0xFE, bytes_received);
    if (start > 0) {
        if ((start - buffer) + 9 < bytes_received) {
            if (start[8] == 0xAA) {
                for (unsigned int i = 0; i < 9; i++) {
                    printf("0x%x\t", *start++);
                }
                printf("\n");
            }
        }
    }
}

max_stars_repo_name: mindThomas/JetsonCar

max_issues_repo_name: mindThomas/JetsonCar

max_forks_repo_name: mindThomas/JetsonCar


text:
// Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin 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 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin.  If not, see <http://www.gnu.org/licenses/>.

#include "ConsoleHandler.h"

#include <iostream>
#include <iomanip>
#include <sstream>

#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <Windows.h>
#else
#include <unistd.h>
#include <stdio.h>
#endif

#include <boost/algorithm/string.hpp>

using Common::Console::Color;

namespace Common {

  /////////////////////////////////////////////////////////////////////////////
  // AsyncConsoleReader
  /////////////////////////////////////////////////////////////////////////////
  AsyncConsoleReader::AsyncConsoleReader() : m_stop(true) {
  }

  AsyncConsoleReader::~AsyncConsoleReader() {
    stop();
  }

  void AsyncConsoleReader::start() {
    m_stop = false;
    m_thread = std::thread(std::bind(&AsyncConsoleReader::consoleThread, this));
  }

  bool AsyncConsoleReader::getline(std::string& line) {
    return m_queue.pop(line);
  }

  void AsyncConsoleReader::pause() {
    if (m_stop) {
      return;
    }

    m_stop = true;

    if (m_thread.joinable()) {
      m_thread.join();
    }

    m_thread = std::thread();
  }

  void AsyncConsoleReader::unpause() {
    start();
  }

  void AsyncConsoleReader::stop() {

    if (m_stop) {
      return; // already stopping/stopped
    }

    m_stop = true;
    m_queue.close();
#ifdef _WIN32
    ::CloseHandle(::GetStdHandle(STD_INPUT_HANDLE));
#endif

    if (m_thread.joinable()) {
      m_thread.join();
    }

    m_thread = std::thread();
  }

  bool AsyncConsoleReader::stopped() const {
    return m_stop;
  }

  void AsyncConsoleReader::consoleThread() {

    while (waitInput()) {
      std::string line;

      if (!std::getline(std::cin, line)) {
        break;
      }

      if (!m_queue.push(line)) {
        break;
      }
    }
  }

  bool AsyncConsoleReader::waitInput() {
#ifndef _WIN32
    int stdin_fileno = ::fileno(stdin);

    while (!m_stop) {
      fd_set read_set;
      FD_ZERO(&read_set);
      FD_SET(stdin_fileno, &read_set);

      struct timeval tv;
      tv.tv_sec = 0;
      tv.tv_usec = 100 * 1000;

      int retval = ::select(stdin_fileno + 1, &read_set, NULL, NULL, &tv);

      if (retval == -1 && errno == EINTR) {
        continue;
      }

      if (retval < 0) {
        return false;
      }

      if (retval > 0) {
        return true;
      }
    }
#endif

    return !m_stop;
  }

  /////////////////////////////////////////////////////////////////////////////
  // ConsoleHandler
  /////////////////////////////////////////////////////////////////////////////
  ConsoleHandler::~ConsoleHandler() {
    stop();
  }

  void ConsoleHandler::start(bool startThread, const std::string& prompt, Console::Color promptColor) {
    m_prompt = prompt;
    m_promptColor = promptColor;
    m_consoleReader.start();

    if (startThread) {
      m_thread = std::thread(std::bind(&ConsoleHandler::handlerThread, this));
    } else {
      handlerThread();
    }
  }

  void ConsoleHandler::stop() {
    requestStop();
    wait();
  }

  void ConsoleHandler::pause() {
    m_consoleReader.pause();
  }

  void ConsoleHandler::unpause() {
    m_consoleReader.unpause();
  }

  void ConsoleHandler::wait() {

    try {
      if (m_thread.joinable()) {
        m_thread.join();
      }
    } catch (std::exception& e) {
      std::cerr << "Exception in ConsoleHandler::wait - " << e.what() << std::endl;
    }
  }

  void ConsoleHandler::requestStop() {
    m_consoleReader.stop();
  }

  std::string ConsoleHandler::getUsage() const {

    if (m_handlers.empty()) {
      return std::string();
    }

    std::stringstream ss;

    size_t maxlen = std::max_element(m_handlers.begin(), m_handlers.end(), [](
      CommandHandlersMap::const_reference& a, CommandHandlersMap::const_reference& b) {
        return a.first.size() < b.first.size(); })->first.size();

    for (auto& x : m_handlers) {
      ss << std::left << std::setw(maxlen + 3) << x.first << x.second.second << std::endl;
    }

    return ss.str();
  }

  void ConsoleHandler::setHandler(const std::string& command, const ConsoleCommandHandler& handler, const std::string& usage) {
    m_handlers[command] = std::make_pair(handler, usage);
  }

  bool ConsoleHandler::runCommand(const std::vector<std::string>& cmdAndArgs) {
    if (cmdAndArgs.size() == 0) {
      return false;
    }

    const auto& cmd = cmdAndArgs.front();
    auto hIter = m_handlers.find(cmd);

    if (hIter == m_handlers.end()) {
      std::cout << "Unknown command: " << cmd << std::endl;
      return false;
    }

    std::vector<std::string> args(cmdAndArgs.begin() + 1, cmdAndArgs.end());
    hIter->second.first(args);
    return true;
  }

  void ConsoleHandler::handleCommand(const std::string& cmd) {
    std::vector<std::string> args;
    boost::split(args, cmd, boost::is_any_of(" "), boost::token_compress_on);
    runCommand(args);
  }

  void ConsoleHandler::handlerThread() {
    std::string line;

    while(!m_consoleReader.stopped()) {
      try {
        if (!m_prompt.empty()) {
          if (m_promptColor != Color::Default) {
            Console::setTextColor(m_promptColor);
          }

          std::cout << m_prompt;
          std::cout.flush();

          if (m_promptColor != Color::Default) {
            Console::setTextColor(Color::Default);
          }
        }

        if (!m_consoleReader.getline(line)) {
          break;
        }

        boost::algorithm::trim(line);
        if (!line.empty()) {
          handleCommand(line);
        }

      } catch (std::exception&) {
        // ignore errors
      }
    }
  }
}


text:
//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2017 Via Technology Ltd. All Rights Reserved.
// (ken dot barker at via-technology dot co dot uk)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//////////////////////////////////////////////////////////////////////////////
#include "via/thread/threadsafe_hash_map.hpp"
#include <boost/test/unit_test.hpp>
#include <iostream>

using namespace via::thread;

//////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_SUITE(Test_Threadsafe_Hash_Map)

BOOST_AUTO_TEST_CASE(Default_Single_Threaded_1)
{
  threadsafe_hash_map<int, int> test_hash_map;
  BOOST_CHECK_EQUAL(19u, test_hash_map.bucket_count());

  BOOST_CHECK((19u + 1u) * 64u <= sizeof(threadsafe_hash_map<int, int>));

  typedef threadsafe_hash_map<int, int>::value_type vt;

  // Test an empty map
  BOOST_CHECK(test_hash_map.empty());
  auto bucket_data(test_hash_map.data());
  BOOST_CHECK_EQUAL(0u, bucket_data.size());

  auto test_value(test_hash_map.find(1));
  BOOST_CHECK_EQUAL(0, test_value.first);
  BOOST_CHECK_EQUAL(0, test_value.second);

  test_value = test_hash_map.find(1, vt(-2, -1));
  BOOST_CHECK_EQUAL(-2, test_value.first);
  BOOST_CHECK_EQUAL(-1, test_value.second);

  // Add a key, value pair
  test_hash_map.insert(vt(1, 10));
  BOOST_CHECK(!test_hash_map.empty());
  bucket_data = test_hash_map.data();
  BOOST_CHECK_EQUAL(1u, bucket_data.size());

  BOOST_CHECK_EQUAL(10, test_hash_map.find(1).second);
  BOOST_CHECK_EQUAL(0, test_hash_map.find(2).second);
  BOOST_CHECK_EQUAL(-1, test_hash_map.find(2, vt(-2, -1)).second);

  // Add another key, value pair
  test_hash_map.insert(vt(2, 20));
  BOOST_CHECK(!test_hash_map.empty());
  bucket_data = test_hash_map.data();
  BOOST_CHECK_EQUAL(2u, bucket_data.size());

  BOOST_CHECK_EQUAL(10, test_hash_map.find(1).second);
  BOOST_CHECK_EQUAL(20, test_hash_map.find(2).second);
  BOOST_CHECK_EQUAL(0, test_hash_map.find(40).second);

  // Add another key, value pair at the same hash as 2
  test_hash_map.emplace(40, 210);
  BOOST_CHECK(!test_hash_map.empty());
  bucket_data = test_hash_map.data();
  BOOST_CHECK_EQUAL(3u, bucket_data.size());

  BOOST_CHECK_EQUAL(10, test_hash_map.find(1).second);
  BOOST_CHECK_EQUAL(20, test_hash_map.find(2).second);
  BOOST_CHECK_EQUAL(210, test_hash_map.find(40).second);
  BOOST_CHECK_EQUAL(-1, test_hash_map.find(31, vt(-2,-1)).second);

  // Add another key, value pair at the same hash as 2
  test_hash_map.emplace(21, 110);
  BOOST_CHECK(!test_hash_map.empty());
  bucket_data = test_hash_map.data();
  BOOST_CHECK_EQUAL(4u, bucket_data.size());

  // Change a value
  test_hash_map.insert(vt(2, 200));
  BOOST_CHECK_EQUAL(200, test_hash_map.find(2).second);
  bucket_data = test_hash_map.data();
  BOOST_CHECK_EQUAL(4u, bucket_data.size());

  // Remove a value
  test_hash_map.erase(2);
  BOOST_CHECK_EQUAL(0, test_hash_map.find(2).second);
  bucket_data = test_hash_map.data();
  BOOST_CHECK_EQUAL(3u, bucket_data.size());

  // Clear the map
  test_hash_map.clear();
  BOOST_CHECK(test_hash_map.empty());
  bucket_data = test_hash_map.data();
  BOOST_CHECK_EQUAL(0u, bucket_data.size());
}

BOOST_AUTO_TEST_SUITE_END()
//////////////////////////////////////////////////////////////////////////////

max_stars_repo_name: JanSimek/via-httplib

max_issues_repo_name: JanSimek/via-httplib

max_forks_repo_name: JanSimek/via-httplib


text:
// this file is just for testing!

#include "stdafx.h"
#include <boost/thread.hpp>
#include <string>
#include <fstream>
#include <streambuf>
#include "MSPBSL_PhysicalInterfaceSerialUART.h"
#include "MSPBSL_Connection5xxUSB.h"
#include "MSPBSL_PacketHandler5xxUART.h"
#include "MSPBSL_PacketHandler1xx_2xx_4xxUART.h"
#include "MSPBSL_Factory.h"
#include "MSPBSL_Connection5xxUART.h"
#include "MSPBSL_Connection1xx_2xx_4xx.h"
#include "MSPBSL_Connection_v1_10.h"
#include "MSPBSL_ConnectionFRAMFamily.h"
#include "MSPBSL_CRCEngine.h"
#include "MSPBSL_Connection_v1_6x.h"
#include "MSPBSL_Connection_v2_xx.h"
#include "MSPBSL_Connection_v2_1x.h"
#include "MSPBSL_Connection_v1_4x.h"
#include "MSPBSL_Connection_v1_3x.h"

#define STANDARD_INVOKE   0x01
#define BSL_XXXX_INVOKE   0x02

int _tmain(int argc, _TCHAR* argv[])
{
		uint32_t i,j;

		string initString = "DEVICE:MSP430F1232";
		MSPBSL_Connection* theBSLConnection = MSPBSL_Factory::getMSPBSL_Connection(initString);

		((theBSLConnection->getPacketHandler())->getPhysicalInterface())->invokeBSL();

		//Example for getting a connection manually (without Factory)
		//string initString = " COM:COM1 BAUD:9600 PARITY:EVEN INVOKE:1 ";
		//MSPBSL_PhysicalInterfaceSerialUART* s  = new MSPBSL_PhysicalInterfaceSerialUART( initString ); // Parity handled in object;
		//MSPBSL_PacketHandler1xx_2xx_4xxUART* p = new MSPBSL_PacketHandler1xx_2xx_4xxUART( initString );
		//MSPBSL_Connection_v1_4x* theBSLConnection = new MSPBSL_Connection_v1_4x( initString );
		//p->setPhysicalInterface( s );
		//theBSLConnection->setPacketHandler(p);

		//some buffers for testing
		uint8_t databuf[0x20000];
		uint8_t returnbuf[0x20000];
		string returnbuf2;

		for(i=0; i<0x20000; i++)
			databuf[i]=(0x00FF & i);
		for(i=0; i<0x20000; i++)
			returnbuf[i]=(0);

		//some example commands
		i=((MSPBSL_Connection_v1_6x*)theBSLConnection)->massErase();
		i=((MSPBSL_Connection_v1_6x*)theBSLConnection)->RX_Password();
		i=((MSPBSL_Connection_v1_6x*)theBSLConnection)->RX_DataBlock(databuf, 0x0021C, 0x2);
		i=((MSPBSL_Connection_v1_6x*)theBSLConnection)->loadFile("parser_testfile.txt");
		i=((MSPBSL_Connection_v1_6x*)theBSLConnection)->TX_DataBlock(databuf, 0x9000, 0x11000);

		i=theBSLConnection->TX_DataBlock(returnbuf, 0x0FFA, 2);
		i=theBSLConnection->RX_DataBlock(databuf, 0xE000, 0x0200);
		i=((MSPBSL_Connection_v2_1x*)theBSLConnection)->eraseCheck(0xE008, 8);
		i=theBSLConnection->TX_DataBlock(returnbuf, 0x0E140, 8);
		i=((MSPBSL_Connection_v2_1x*)theBSLConnection)->eraseSegment(0xE000);
		i=((MSPBSL_Connection_v2_1x*)theBSLConnection)->eraseInfoMain(0xFFFF);
		i=((MSPBSL_Connection_v2_1x*)theBSLConnection)->changeBaudrate(0x80, 0x85, 0x00);

       return 0;

}

max_stars_repo_name: KirillSmirnov/trik-mspbsl-library

max_issues_repo_name: KirillSmirnov/trik-mspbsl-library

max_forks_repo_name: KirillSmirnov/trik-mspbsl-library


text:
//******************************************************************************
// RCF - Remote Call Framework
//
// Copyright (c) 2005 - 2013, Delta V Software. All rights reserved.
// http://www.deltavsoft.com
//
// RCF is distributed under dual licenses - closed source or GPL.
// Consult your particular license for conditions of use.
//
// If you have not purchased a commercial license, you are using RCF
// under GPL terms.
//
// Version: 2.0
// Contact: support <at> deltavsoft.com
//
//******************************************************************************

#ifndef INCLUDE_UTIL_ASSERT_HPP
#define INCLUDE_UTIL_ASSERT_HPP

#include <cassert>
#include <cstdio>
#include <exception>

#include <boost/current_function.hpp>

#include "VariableArgMacro.hpp"

#if defined(_MSC_VER) && !defined(NDEBUG)
#include <crtdbg.h>
#endif

#include <RCF/Export.hpp>

namespace RCF {

    class RCF_EXPORT AssertFunctor : public VariableArgMacroFunctor
    {
    public:

        AssertFunctor();
        AssertFunctor(const char * expr);
        ~AssertFunctor();

        const char * mExpr;
    };

    class VarArgAbort
    {
    public:
        VarArgAbort();

        template<typename T>
        VarArgAbort &operator()(const T &)
        {
            return *this;
        }
    };

#if 0
#define UTIL_ASSERT_DEBUG(cond, e, logName, logLevel)                       \
    if (cond) ;                                                             \
    else RCF::VarArgAssert(__FILE__, __LINE__, #cond)
#endif

#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 4355 )  // warning C4355: 'this' : used in base member initializer list
#endif

#if defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4))
#define UTIL_ASSERT_DEBUG_GCC_33_HACK (const RCF::VariableArgMacro<RCF::ThrowFunctor> &)
#else
#define UTIL_ASSERT_DEBUG_GCC_33_HACK
#endif

    DECLARE_VARIABLE_ARG_MACRO( UTIL_ASSERT_DEBUG, RCF::AssertFunctor );
    #define UTIL_ASSERT_DEBUG(expr, e, logName, logLevel)                                    \
        if (expr);    \
        else\
            UTIL_ASSERT_DEBUG_GCC_33_HACK                                              \
            RCF::VariableArgMacro<RCF::AssertFunctor>(#expr)    \
                .init(                                                          \
                    "",                                                         \
                    "",                                                         \
                    __FILE__,                                                   \
                    __LINE__,                                                   \
                    BOOST_CURRENT_FUNCTION)                                     \
                .cast( (RCF::VariableArgMacro<RCF::AssertFunctor> *) NULL)     \
                .UTIL_ASSERT_DEBUG_A

    #define UTIL_ASSERT_DEBUG_A(x)               UTIL_ASSERT_DEBUG_OP(x, B)
    #define UTIL_ASSERT_DEBUG_B(x)               UTIL_ASSERT_DEBUG_OP(x, A)
    #define UTIL_ASSERT_DEBUG_OP(x, next)        UTIL_ASSERT_DEBUG_A.notify_((x), #x).UTIL_ASSERT_DEBUG_ ## next

#ifdef _MSC_VER
#pragma warning( pop )
#endif

    #ifdef RCF_ALWAYS_ABORT_ON_ASSERT

    #define UTIL_ASSERT_RELEASE(cond, e, logName, logLevel)                     \
        if (cond) ;                                                             \
        else RCF::VarArgAbort()

    #else

    #define UTIL_ASSERT_RELEASE(cond, e, logName, logLevel)                     \
        if (cond) ;                                                             \
        else UTIL_THROW(e, logName, logLevel)(cond)

    #endif

    #define UTIL_ASSERT_NULL(cond, E)                                           \
        DUMMY_VARIABLE_ARG_MACRO()

    #ifdef NDEBUG
    #define UTIL_ASSERT UTIL_ASSERT_RELEASE
    #else
    #define UTIL_ASSERT UTIL_ASSERT_DEBUG
    #endif

} // namespace RCF

#endif //! INCLUDE_UTIL_ASSERT_HPP

max_stars_repo_name: ASMlover/study

max_issues_repo_name: ASMlover/study

max_forks_repo_name: ASMlover/study


text:
//==============================================================================
//         Copyright 2003 - 2011   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef BOOST_SIMD_SDK_DSL_LAMBDA_GENERATOR_HPP_INCLUDED
#define BOOST_SIMD_SDK_DSL_LAMBDA_GENERATOR_HPP_INCLUDED

#include <boost/proto/transform.hpp>
#include <boost/dispatch/attributes.hpp>
#include <boost/mpl/apply.hpp>

namespace boost { namespace simd { namespace meta
{
  template<class Lambda>
  struct lambda_generator
    : proto::transform< lambda_generator<Lambda> >
  {
    template<class Expr, class State, class Data>
    struct impl : proto::transform_impl<Expr, State, Data>
    {
        typedef typename mpl::apply1<Lambda, typename boost::remove_const<typename impl::expr>::type>::type result_type;

        BOOST_DISPATCH_FORCE_INLINE
        result_type
        operator()( typename impl::expr_param e
                  , typename impl::state_param s
                  , typename impl::data_param d
                  ) const
        {
          return result_type(e);
        }
    };
  };

  template<class Lambda>
  struct lambda_pod_generator
    : proto::transform< lambda_pod_generator<Lambda> >
  {
    template<class Expr, class State, class Data>
    struct impl : proto::transform_impl<Expr, State, Data>
    {
        typedef typename mpl::apply1<Lambda, typename boost::remove_const<typename impl::expr>::type>::type result_type;

        BOOST_DISPATCH_FORCE_INLINE
        result_type
        operator()( typename impl::expr_param e
                  , typename impl::state_param
                  , typename impl::data_param
                  ) const
        {
          result_type const that = {e};
          return that;
        }
    };
  };
} } }

#endif


text:
/**
 * Copyright Soramitsu Co., Ltd. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

#include <gtest/gtest.h>
#include <boost/variant.hpp>
#include "backend/protobuf/transaction.hpp"
#include "builders/protobuf/queries.hpp"
#include "cryptography/crypto_provider/crypto_defaults.hpp"
#include "framework/integration_framework/integration_test_framework.hpp"
#include "integration/acceptance/acceptance_fixture.hpp"
#include "interfaces/query_responses/transactions_response.hpp"
#include "utils/query_error_response_visitor.hpp"

using namespace integration_framework;
using namespace shared_model;
using namespace common_constants;

class GetTransactions : public AcceptanceFixture {
 public:
  /**
   * Creates the transaction with the user creation commands
   * @param perms are the permissions of the user
   * @return built tx and a hash of its payload
   */
  auto makeUserWithPerms(const interface::RolePermissionSet &perms = {
                             interface::permissions::Role::kGetMyTxs}) {
    auto new_perms = perms;
    new_perms.set(interface::permissions::Role::kSetQuorum);
    return AcceptanceFixture::makeUserWithPerms(kNewRole, new_perms);
  }

  /**
   * Valid transaction that user can execute.
   * @return built tx and a hash of its payload
   * Note: It should affect the ledger minimally
   */
  auto dummyTx() {
    return complete(AcceptanceFixture::baseTx().setAccountQuorum(kUserId, 1));
  }

  /**
   * Creates valid GetTransactions query of current user
   * @param hash of the tx for querying
   * @return built query
   */
  auto makeQuery(const crypto::Hash &hash) {
    return complete(baseQry().queryCounter(1).getTransactions(
        std::vector<crypto::Hash>{hash}));
  }

  const std::string kNewRole = "rl";
};

/**
 * @given some user without can_get_{my,all}_txs permissions
 * @when query GetTransactions of existing transaction of the user
 * @then stateful validation fail returned
 */
TEST_F(GetTransactions, HaveNoGetPerms) {
  auto check = [](auto &status) {
    ASSERT_TRUE(
        boost::apply_visitor(interface::QueryErrorResponseChecker<
                                 interface::StatefulFailedErrorResponse>(),
                             status.get()));
  };

  auto dummy_tx = dummyTx();
  IntegrationTestFramework(1)
      .setInitialState(kAdminKeypair)
      .sendTx(makeUserWithPerms({interface::permissions::Role::kReadAssets}))
      .skipProposal()
      .skipBlock()
      .sendTxAwait(
          dummy_tx,
          [](auto &block) { ASSERT_EQ(block->transactions().size(), 1); })
      .sendQuery(makeQuery(dummy_tx.hash()), check);
}

/**
 * @given some user with only can_get_all_txs permission
 * @when query GetTransactions of existing transaction of the user
 * @then receive TransactionsResponse with the transaction hash
 */
TEST_F(GetTransactions, HaveGetAllTx) {
  auto dummy_tx = dummyTx();
  auto check = [&dummy_tx](auto &status) {
    ASSERT_NO_THROW({
      const auto &resp =
          boost::get<const shared_model::interface::TransactionsResponse &>(
              status.get());
      ASSERT_EQ(resp.transactions().size(), 1);
      ASSERT_EQ(resp.transactions().front(), dummy_tx);
    });
  };

  IntegrationTestFramework(1)
      .setInitialState(kAdminKeypair)
      .sendTx(makeUserWithPerms({interface::permissions::Role::kGetAllTxs}))
      .skipProposal()
      .skipBlock()
      .sendTxAwait(
          dummy_tx,
          [](auto &block) { ASSERT_EQ(block->transactions().size(), 1); })
      .sendQuery(makeQuery(dummy_tx.hash()), check);
}

/**
 * @given some user with only can_get_my_txs permission
 * @when query GetTransactions of existing transaction of the user
 * @then receive TransactionsResponse with the transaction hash
 */
TEST_F(GetTransactions, HaveGetMyTx) {
  auto dummy_tx = dummyTx();
  auto check = [&dummy_tx](auto &status) {
    ASSERT_NO_THROW({
      const auto &resp =
          boost::get<const shared_model::interface::TransactionsResponse &>(
              status.get());
      ASSERT_EQ(resp.transactions().size(), 1);
      ASSERT_EQ(resp.transactions().front(), dummy_tx);
    });
  };

  IntegrationTestFramework(1)
      .setInitialState(kAdminKeypair)
      .sendTx(makeUserWithPerms())
      .skipProposal()
      .skipBlock()
      .sendTxAwait(
          dummy_tx,
          [](auto &block) { ASSERT_EQ(block->transactions().size(), 1); })
      .sendQuery(makeQuery(dummy_tx.hash()), check);
}

/**
 * @given some user with only can_get_my_txs permission
 * @when query GetTransactions of existing transaction of the user, but with
 * invalid signatures
 * @then receive StatefullErrorResponse
 */
TEST_F(GetTransactions, InvalidSignatures) {
  auto dummy_tx = dummyTx();
  auto check = [](auto &status) {
    ASSERT_NO_THROW({
      const auto &error_rsp =
          boost::get<const shared_model::interface::ErrorQueryResponse &>(
              status.get());
      boost::get<const shared_model::interface::StatefulFailedErrorResponse &>(
          error_rsp.get());
    });
  };

  auto query = baseQry()
                   .queryCounter(1)
                   .getTransactions(std::vector<crypto::Hash>{dummy_tx.hash()})
                   .build()
                   .signAndAddSignature(
                       crypto::DefaultCryptoAlgorithmType::generateKeypair())
                   .finish();

  IntegrationTestFramework(1)
      .setInitialState(kAdminKeypair)
      .sendTx(makeUserWithPerms())
      .skipProposal()
      .skipVerifiedProposal()
      .skipBlock()
      .sendQuery(query, check);
}

/**
 * @given some user with only can_get_my_txs permission
 * @when query GetTransactions with nonexistent hash
 * @then TransactionsResponse with no transactions
 */
TEST_F(GetTransactions, NonexistentHash) {
  auto check = [](auto &status) {
    ASSERT_NO_THROW({
      const auto &resp =
          boost::get<const shared_model::interface::TransactionsResponse &>(
              status.get());
      ASSERT_EQ(resp.transactions().size(), 0);
    });
  };

  IntegrationTestFramework(1)
      .setInitialState(kAdminKeypair)
      .sendTxAwait(
          makeUserWithPerms(),
          [](auto &block) { ASSERT_EQ(block->transactions().size(), 1); })
      .sendQuery(makeQuery(crypto::Hash(std::string(
                     crypto::DefaultCryptoAlgorithmType::kHashLength, '0'))),
                 check);
}

/**
 * @given some user with can_get_my_txs
 * @when query GetTransactions of existing transaction of the other user
 * @then TransactionsResponse with no transactions
 */
TEST_F(GetTransactions, OtherUserTx) {
  auto check = [](auto &status) {
    ASSERT_NO_THROW({
      const auto &resp =
          boost::get<const shared_model::interface::TransactionsResponse &>(
              status.get());
      ASSERT_EQ(resp.transactions().size(), 0);
    });
  };

  auto tx = makeUserWithPerms();
  IntegrationTestFramework(1)
      .setInitialState(kAdminKeypair)
      .sendTxAwait(
          tx, [](auto &block) { ASSERT_EQ(block->transactions().size(), 1); })
      .sendQuery(makeQuery(tx.hash()), check);
}

max_stars_repo_name: coderintherye/iroha

max_issues_repo_name: coderintherye/iroha

max_forks_repo_name: coderintherye/iroha


text:
// This file is part of the dune-xt project:
//   https://zivgitlab.uni-muenster.de/ag-ohlberger/dune-community/dune-xt
// Copyright 2009-2021 dune-xt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2012, 2014 - 2017, 2020)
//   René Fritze     (2010 - 2013, 2015 - 2016, 2018 - 2020)
//   Stefan Girke    (2012)
//   Tobias Leibner  (2014, 2016 - 2018, 2020)

#ifndef DUNE_XT_COMMON_TUPLE_HH
#define DUNE_XT_COMMON_TUPLE_HH

#include <tuple>
#include <type_traits>
#include <utility>

#include <boost/mpl/if.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/vector.hpp>

#define TMAX(t_, no_) (std::tuple_size<t_>::value >= (no_ + 1) ? no_ : 0)
#define TELE(t_, s_, no_) typename std::tuple_element<TMAX(t_, no_), t_>::type::s_

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, size_t Size>
struct RightTrimTuple
{
  using type = std::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>;
};

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct RightTrimTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, 9>
{
  using type = std::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>;
};

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct RightTrimTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, 8>
{
  using type = std::tuple<T1, T2, T3, T4, T5, T6, T7, T8>;
};

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct RightTrimTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, 7>
{
  using type = std::tuple<T1, T2, T3, T4, T5, T6, T7>;
};

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct RightTrimTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, 6>
{
  using type = std::tuple<T1, T2, T3, T4, T5, T6>;
};

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct RightTrimTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, 5>
{
  using type = std::tuple<T1, T2, T3, T4, T5>;
};

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct RightTrimTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, 4>
{
  using type = std::tuple<T1, T2, T3, T4>;
};

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct RightTrimTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, 3>
{
  using type = std::tuple<T1, T2, T3>;
};

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct RightTrimTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, 2>
{
  using type = std::tuple<T1, T2>;
};

template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
struct RightTrimTuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, 1>
{
  using type = std::tuple<T1>;
};

#define TUPLE_TYPEDEFS_2_TUPLE(t_, s_)                                                                                \
  typename RightTrimTuple<TELE(t_, s_, 0),                                                                             \
                          TELE(t_, s_, 1),                                                                             \
                          TELE(t_, s_, 2),                                                                             \
                          TELE(t_, s_, 3),                                                                             \
                          TELE(t_, s_, 4),                                                                             \
                          TELE(t_, s_, 5),                                                                             \
                          TELE(t_, s_, 6),                                                                             \
                          TELE(t_, s_, 7),                                                                             \
                          TELE(t_, s_, 8),                                                                             \
                          std::tuple_size<t_>::value>::type

/**
 * @def TUPLE_TYPEDEFS_2_TUPLE( t_, s_ )
 *
 * @brief extracts types of the elements of a std::tuple and
 * creates a new std::tuple with these extracted types.
 *
 * first argument: the tuple type
 * second argument: the typedef of the elements of the tuple
 *
 * example:
 * Let two classes be given:
 *
 * @code
 * class A
 * {
 *   public:
 *   using MyFancyType = int;
 * };
 *
 * class B
 * {
 *   public:
 *   using MyFancyType = int;
 * };
 * @endcode
 *
 * Define a tuple, i.e.
 *
 * @code
 * typedef std::tuple< A, B, B >
 *   MyTuple;
 * @endcode
 *
 * Instead of writing
 *
 * @code
 * typedef std::tuple< typename tuple_element<0,MyTuple>::type::MyFancyType,
 *                      typename tuple_element<1,MyTuple>::type::MyFancyType,
 *                      typename tuple_element<2,MyTuple>::type::MyFancyType >
 *   MySubTupleType;
 * @endcode
 *
 * just write
 *
 * @code
 * typedef TUPLE_TYPEDEFS_2_TUPLE( MyTuple, MyFancyType )
 *   MySubTupleType;
 * @endcode
 *
 * without (general) restriction to the size
 * of the tuple @c MyTuple. Enjoy it!
 */

namespace Dune::XT::Common {

// reduced from
// http://stackoverflow.com/questions/1492204/is-it-possible-to-generate-types-with-all-combinations-of-template-arguments
namespace TupleProduct {
using boost::mpl::begin;
using boost::mpl::deref;
using boost::mpl::end;
using boost::mpl::if_;
using boost::mpl::next;

struct end_of_recursion_tag
{
  template <class... Args>
  static void Run(Args&&... /*args*/)
  {}
};

template <class UTypes, // Forward Sequence, e.g. boost::mpl::vector
          class VTypes, // Forward Sequence, e.g. boost::mpl::vector
          class TestFunc // class type that has a nested templated run() member function
          >
struct Combine
{
  // forward declaration
  template <class UIterator, class VIterator>
  struct Generate;

  // this class implements recursion body
  template <class UIterator, class VIterator>
  struct Next
  {
    // u_begin is not necessary ;)
    // it would be cheaper not to pre-declare all of them since we force evaluation
    // however this dramatically increase the readability
    using v_begin = typename begin<VTypes>::type;

    using u_end = typename end<UTypes>::type;
    using v_end = typename end<VTypes>::type;

    using u_next = typename next<UIterator>::type;
    using v_next = typename next<VIterator>::type;

    using type =
        typename if_<std::is_same<v_next, v_end>,
                     typename if_<std::is_same<u_next, u_end>, end_of_recursion_tag, Generate<u_next, v_begin>>::type,
                     Generate<UIterator, v_next>>::type;
  };

  //  this class run test on generated types in thos round and go to next*/
  template <class UIterator = typename begin<UTypes>::type, class VIterator = typename begin<VTypes>::type>
  struct Generate
  {
    //  generate <<next>> target type
    using next_type = typename Next<UIterator, VIterator>::type;

    static void Run()
    {
      // test on the generated types of this round of recursion
      TestFunc::template run<typename deref<UIterator>::type, typename deref<VIterator>::type>();

      // go to the next round of recursion
      next_type::Run();
    }

    template <class... Args>
    static void Run(Args&&... args)
    {
      // test on the generated types of this round of recursion
      TestFunc::template run<typename deref<UIterator>::type, typename deref<VIterator>::type>(
          std::forward<Args>(args)...);

      // go to the next round of recursion
      next_type::Run(std::forward<Args>(args)...);
    }
  };
};

} // namespace TupleProduct

//! from https://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence/17426611
template <size_t... Is>
struct index_sequence
{
  using type = index_sequence;
};

namespace internal {

template <class S1, class S2>
struct Concat;
template <class S1, class S2>
using Concat_t = typename Concat<S1, S2>::type;

template <size_t... I1, size_t... I2>
struct Concat<index_sequence<I1...>, index_sequence<I2...>>
{
  using type = index_sequence<I1..., (sizeof...(I1) + I2)...>;
};

} // namespace internal

template <size_t N>
struct make_index_sequence;
template <size_t N>
using make_index_sequence_t = typename make_index_sequence<N>::type;

template <size_t N>
struct make_index_sequence
{
  using type = internal::Concat_t<make_index_sequence_t<N / 2>, make_index_sequence_t<N - N / 2>>;
};

// break conditions
template <>
struct make_index_sequence<1>
{
  using type = index_sequence<0>;
};
template <>
struct make_index_sequence<0>
{
  using type = index_sequence<>;
};

//! T_aliased< T, Index > is always the type T, no matter what index is
template <typename T, std::size_t index>
using T_aliased = T;

//! make_identical_tuple< T, N >::type is a std::tuple< T, ... , T > with a length of N
template <typename T, std::size_t N, typename I = typename make_index_sequence<N>::type>
struct make_identical_tuple;

template <typename T, std::size_t N, std::size_t... Indices>
struct make_identical_tuple<T, N, index_sequence<Indices...>>
{
  using type = std::tuple<T_aliased<T, Indices>...>;

  static type create(const T& t)
  {
    return type(T_aliased<T, Indices>{t}...);
  }
};

//! implementation of std::tuple_element with O(log(N)) template recursion depth
//! from https://stackoverflow.com/questions/18593057/stdtuple-element-need-deep-template-instantination
namespace internal {
template <std::size_t>
struct Any
{
  Any(...){}; // NOLINT(modernize-use-equals-default)
};

template <typename T>
struct wrapper
{
  using type = T;
};

template <std::size_t... Is>
struct get_nth_helper
{
  template <typename T>
  static auto deduce(Any<Is>..., wrapper<T>, ...) -> wrapper<T>;
};

template <std::size_t... Is, typename... Ts>
auto deduce_seq(index_sequence<Is...>, wrapper<Ts>... pp) -> decltype(get_nth_helper<Is...>::deduce(pp...));
} // namespace internal

template <std::size_t N, class Tuple>
struct tuple_element;

template <std::size_t N, class... Ts>
struct tuple_element<N, std::tuple<Ts...>>
{
  using wrapped_type = decltype(internal::deduce_seq(make_index_sequence_t<N>{}, internal::wrapper<Ts>()...));
  using type = typename wrapped_type::type;
};

struct tuple_null_type
{};
struct null_type
{};

template <typename TList>
struct list_content;

template <typename Head, typename... Tail>
struct list_content<std::tuple<Head, Tail...>>
{
  using head = Head;
  using tail = std::tuple<Tail...>;
};

template <typename T>
struct list_content<std::tuple<T>>
{
  using head = T;
  using tail = tuple_null_type;
};

template <typename T1>
using tuple_head_t = typename list_content<T1>::head;
template <typename T1>
using tuple_tail_t = typename list_content<T1>::tail;

/** These classes allow recursively visiting a typelist that may contain templates names
 *  So if you ever wanted to iterate over "AllDirichletBoundaryInfo, AllNeumannBoundaryInfo, etc"
 *  and then input another type as tpl arg, this is for you.
 *
 * **/

//! use this to wrap template classes into the template_tuple
template <template <class...> class B>
struct tplwrap
{};

template <class... Ms>
class template_tuple;

namespace internal {
template <class B, class...>
struct from_tplwrap
{
  using type = B;
};

template <template <class...> class B, class... T>
struct from_tplwrap<tplwrap<B>, T...>
{
  using type = B<T...>;
};

template <class... Templates>
struct type_help
{
  template <class... Parameters>
  using type = std::tuple<typename from_tplwrap<Templates, Parameters...>::type...>;
};

template <class... Args>
struct type_help<std::tuple<Args...>>
{
  template <class...>
  using type = std::tuple<Args...>;
};

template <class... Args>
struct tail_hlp
{
  using type = template_tuple<Args...>;
};

template <class... Args>
struct tail_hlp<std::tuple<Args...>>
{
  using type = template_tuple<Args...>;
};

template <class A>
struct head_hlp
{
  using type = A;
};

template <class A, class B>
struct head_hlp<std::tuple<A, B>>
{
  using type = A;
};
} // namespace internal

template <class... WrapperOrTypes>
class template_tuple
{

public:
  template <typename... T>
  using type = typename internal::type_help<WrapperOrTypes...>::template type<T...>;
  template <typename... T>
  using tail_type = typename internal::tail_hlp<tuple_tail_t<type<T...>>>::type;
  template <typename... T>
  using head_type = typename internal::head_hlp<tuple_head_t<type<T...>>>::type;
};

template <typename Head, typename... Tail>
struct list_content<template_tuple<Head, Tail...>>
{
  template <class... Parameters>
  using head = typename internal::from_tplwrap<Head, Parameters...>::type;
  using tail = template_tuple<Tail...>;
};

template <typename T>
struct list_content<template_tuple<T>>
{
  template <class... Parameters>
  using head = typename internal::from_tplwrap<T, Parameters...>::type;
  using tail = tuple_null_type;
};

using null_template_tuple = template_tuple<Dune::XT::Common::tuple_null_type>;

template <typename... input_t>
using tuple_cat_t = decltype(std::tuple_cat(std::declval<input_t>()...));

} // namespace Dune::XT::Common

namespace std {
//! specialization for our custom tuple tuple_size can be use on it
template <class... Types>
struct tuple_size<Dune::XT::Common::template_tuple<Types...>>
  : public std::integral_constant<std::size_t, sizeof...(Types)>
{};

} // namespace std
#endif // DUNE_XT_COMMON_TUPLE_HH

ext: hh

max_stars_repo_name: dune-community/dune-xt

max_issues_repo_name: dune-community/dune-xt

max_forks_repo_name: dune-community/dune-xt


text: #include <boost/units/physical_dimensions/plane_angle.hpp>