<commit_before>#include <karl/api/response_handler.hpp>

#include <supermarx/serialization/xml_serializer.hpp>
#include <supermarx/serialization/msgpack_serializer.hpp>
#include <supermarx/serialization/msgpack_compact_serializer.hpp>
#include <supermarx/serialization/json_serializer.hpp>

#include <supermarx/serialization/msgpack_deserializer.hpp>

#include <supermarx/serialization/serialize_fusion.hpp>
#include <supermarx/serialization/deserialize_fusion.hpp>

#include <supermarx/api/add_product.hpp>

#include <karl/api/api_exception.hpp>
#include <karl/api/uri.hpp>

#include <karl/util/log.hpp>
#include <karl/util/guard.hpp>

namespace supermarx
{

void init_serializer(request& r, response_handler::serializer_ptr& s)
{
	const guard g([&]()
	{
		//Fall back to XML
		if(s == nullptr)
		{
			s.reset(new xml_serializer());
			r.write_header("Content-Type", "application/xml");
		}
	});

	const auto& format = r.env().gets.find("format");
	if(format == r.env().gets.end() || format->second == "xml")
	{
		s.reset(new xml_serializer());
		r.write_header("Content-Type", "application/xml");
	}
	else if(format->second == "json")
		s.reset(new json_serializer());
	else if(format->second == "msgpack")
		s.reset(new msgpack_serializer());
	else if(format->second == "msgpack_compact")
		s.reset(new msgpack_compact_serializer());
	else
		throw api_exception::format_unknown;
}

bool url_decode(const std::string& in, std::string& out)
{
	out.clear();
	out.reserve(in.size());

	for(std::size_t i = 0; i < in.size(); ++i)
	{
		if(in[i] == '%')
		{
			if(i + 3 <= in.size())
			{
				int value = 0;
				std::istringstream is(in.substr(i + 1, 2));

				if(is >> std::hex >> value)
				{
					out += static_cast<char>(value);
					i += 2;
				}
				else
					return false;
			}
			else
				return false;
		}
		else if(in[i] == '+')
			out += ' ';
		else
			out += in[i];
	}

	return true;
}

void write_exception(request& r, response_handler::serializer_ptr& s, api_exception e)
{
	s->clear(); //Clear any previous content

	r.write_header("Status", api_exception_status(e));

	s->write_object("exception", 3);
	s->write("code", e);
	s->write("message", api_exception_message(e));
	s->write("help", "http://supermarx.nl/docs/api_exception/" + boost::lexical_cast<std::string>(e) + "/");
}

std::string fetch_payload(const request& r)
{
	const auto payload_itr = r.env().posts.find("payload");
	if(payload_itr == r.env().posts.end())
		throw api_exception::payload_expected;

	return payload_itr->second.value;
}

template<typename T>
T deserialize_payload(const request& r, const std::string& name)
{
	std::unique_ptr<deserializer> d(new msgpack_deserializer);
	d->feed(fetch_payload(r));

	return deserialize<T>(d, name);
}

template<typename T>
void package(response_handler::serializer_ptr& s, const T& x, const std::string& name)
{
	serialize<T>(s, name, x);
}

bool process(request& r, response_handler::serializer_ptr& s, karl& k, const uri& u)
{
	if(u.match_path(0, "find_products"))
	{
		if(u.path.size() != 3)
			return false;

		id_t supermarket_id = boost::lexical_cast<id_t>(u.path[1]);
		std::string name = u.path[2];

		serialize(s, "products", k.get_products(name, supermarket_id));
		return true;
	}

	if(u.match_path(0, "add_product"))
	{
		if(u.path.size() != 2)
			return false;

		id_t supermarket_id = boost::lexical_cast<id_t>(u.path[1]);
		api::add_product request = deserialize_payload<api::add_product>(r, "addproduct");

		k.add_product(request.p, supermarket_id, request.retrieved_on, request.c);
		s->write_object("response", 1);
		s->write("status", std::string("done"));
		return true;
	}

	if(u.match_path(0, "get_product_summary"))
	{
		if(u.path.size() != 3)
			return false;

		id_t supermarket_id = boost::lexical_cast<id_t>(u.path[1]);
		std::string identifier = u.path[2];

		auto p_opt = k.get_product_summary(identifier, supermarket_id);
		if(!p_opt)
			throw api_exception::product_not_found;

		serialize(s, "product_summary", *p_opt);
		return true;
	}

	return false;
}

void response_handler::respond(request& r, karl& k)
{
	r.write_header("Server", "karl/0.1");

	// Decode url to path.
	std::string request_path;
	if(!url_decode(r.env().requestUri, request_path))
	{
		r.write_header("Status", "400 Bad Request");
		r.write_endofheader();
		return;
	}

	// Request path must be absolute and not contain "..".
	if(request_path.empty() || request_path[0] != '/' || request_path.find("..") != std::string::npos)
	{
		r.write_header("Status", "400 Bad Request");
		r.write_endofheader();
		r.write_text("400 bad request");
		return;
	}

	uri u(request_path);

	serializer_ptr s(nullptr);

	try
	{
		init_serializer(r, s);

		if(process(r, s, k, u))
			r.write_header("Status", "200 OK");
		else
			throw api_exception::path_unknown;
	}
	catch(api_exception e)
	{
		log("api::response_handler", log::WARNING)() << "api_exception - " << api_exception_message(e) << " (" << e << ")";

		write_exception(r, s, e);
	}
	catch(std::exception& e)
	{
		log("api::response_handler", log::ERROR)() << "Uncaught exception: " << e.what();

		write_exception(r, s, api_exception::unknown);
	}
	catch( ... )
	{
		log("api::response_handler", log::ERROR)() << "Unknown exception";

		write_exception(r, s, api_exception::unknown);
	}

	r.write_endofheader();
	s->dump([&](const char* data, size_t size){ r.write_bytes(data, size); });
}

}
<commit_msg>Added application/json stanza to json output<commit_after>#include <karl/api/response_handler.hpp>

#include <supermarx/serialization/xml_serializer.hpp>
#include <supermarx/serialization/msgpack_serializer.hpp>
#include <supermarx/serialization/msgpack_compact_serializer.hpp>
#include <supermarx/serialization/json_serializer.hpp>

#include <supermarx/serialization/msgpack_deserializer.hpp>

#include <supermarx/serialization/serialize_fusion.hpp>
#include <supermarx/serialization/deserialize_fusion.hpp>

#include <supermarx/api/add_product.hpp>

#include <karl/api/api_exception.hpp>
#include <karl/api/uri.hpp>

#include <karl/util/log.hpp>
#include <karl/util/guard.hpp>

namespace supermarx
{

void init_serializer(request& r, response_handler::serializer_ptr& s)
{
	const guard g([&]()
	{
		//Fall back to XML
		if(s == nullptr)
		{
			s.reset(new xml_serializer());
			r.write_header("Content-Type", "application/xml");
		}
	});

	const auto& format = r.env().gets.find("format");
	if(format == r.env().gets.end() || format->second == "xml")
	{
		s.reset(new xml_serializer());
		r.write_header("Content-Type", "application/xml");
	}
	else if(format->second == "json")
	{
		s.reset(new json_serializer());
		r.write_header("Content-Type", "application/json");
	}
	else if(format->second == "msgpack")
		s.reset(new msgpack_serializer());
	else if(format->second == "msgpack_compact")
		s.reset(new msgpack_compact_serializer());
	else
		throw api_exception::format_unknown;
}

bool url_decode(const std::string& in, std::string& out)
{
	out.clear();
	out.reserve(in.size());

	for(std::size_t i = 0; i < in.size(); ++i)
	{
		if(in[i] == '%')
		{
			if(i + 3 <= in.size())
			{
				int value = 0;
				std::istringstream is(in.substr(i + 1, 2));

				if(is >> std::hex >> value)
				{
					out += static_cast<char>(value);
					i += 2;
				}
				else
					return false;
			}
			else
				return false;
		}
		else if(in[i] == '+')
			out += ' ';
		else
			out += in[i];
	}

	return true;
}

void write_exception(request& r, response_handler::serializer_ptr& s, api_exception e)
{
	s->clear(); //Clear any previous content

	r.write_header("Status", api_exception_status(e));

	s->write_object("exception", 3);
	s->write("code", e);
	s->write("message", api_exception_message(e));
	s->write("help", "http://supermarx.nl/docs/api_exception/" + boost::lexical_cast<std::string>(e) + "/");
}

std::string fetch_payload(const request& r)
{
	const auto payload_itr = r.env().posts.find("payload");
	if(payload_itr == r.env().posts.end())
		throw api_exception::payload_expected;

	return payload_itr->second.value;
}

template<typename T>
T deserialize_payload(const request& r, const std::string& name)
{
	std::unique_ptr<deserializer> d(new msgpack_deserializer);
	d->feed(fetch_payload(r));

	return deserialize<T>(d, name);
}

template<typename T>
void package(response_handler::serializer_ptr& s, const T& x, const std::string& name)
{
	serialize<T>(s, name, x);
}

bool process(request& r, response_handler::serializer_ptr& s, karl& k, const uri& u)
{
	if(u.match_path(0, "find_products"))
	{
		if(u.path.size() != 3)
			return false;

		id_t supermarket_id = boost::lexical_cast<id_t>(u.path[1]);
		std::string name = u.path[2];

		serialize(s, "products", k.get_products(name, supermarket_id));
		return true;
	}

	if(u.match_path(0, "add_product"))
	{
		if(u.path.size() != 2)
			return false;

		id_t supermarket_id = boost::lexical_cast<id_t>(u.path[1]);
		api::add_product request = deserialize_payload<api::add_product>(r, "addproduct");

		k.add_product(request.p, supermarket_id, request.retrieved_on, request.c);
		s->write_object("response", 1);
		s->write("status", std::string("done"));
		return true;
	}

	if(u.match_path(0, "get_product_summary"))
	{
		if(u.path.size() != 3)
			return false;

		id_t supermarket_id = boost::lexical_cast<id_t>(u.path[1]);
		std::string identifier = u.path[2];

		auto p_opt = k.get_product_summary(identifier, supermarket_id);
		if(!p_opt)
			throw api_exception::product_not_found;

		serialize(s, "product_summary", *p_opt);
		return true;
	}

	return false;
}

void response_handler::respond(request& r, karl& k)
{
	r.write_header("Server", "karl/0.1");

	// Decode url to path.
	std::string request_path;
	if(!url_decode(r.env().requestUri, request_path))
	{
		r.write_header("Status", "400 Bad Request");
		r.write_endofheader();
		return;
	}

	// Request path must be absolute and not contain "..".
	if(request_path.empty() || request_path[0] != '/' || request_path.find("..") != std::string::npos)
	{
		r.write_header("Status", "400 Bad Request");
		r.write_endofheader();
		r.write_text("400 bad request");
		return;
	}

	uri u(request_path);

	serializer_ptr s(nullptr);

	try
	{
		init_serializer(r, s);

		if(process(r, s, k, u))
			r.write_header("Status", "200 OK");
		else
			throw api_exception::path_unknown;
	}
	catch(api_exception e)
	{
		log("api::response_handler", log::WARNING)() << "api_exception - " << api_exception_message(e) << " (" << e << ")";

		write_exception(r, s, e);
	}
	catch(std::exception& e)
	{
		log("api::response_handler", log::ERROR)() << "Uncaught exception: " << e.what();

		write_exception(r, s, api_exception::unknown);
	}
	catch( ... )
	{
		log("api::response_handler", log::ERROR)() << "Unknown exception";

		write_exception(r, s, api_exception::unknown);
	}

	r.write_endofheader();
	s->dump([&](const char* data, size_t size){ r.write_bytes(data, size); });
}

}
<|endoftext|>


<commit_before>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "bsestartup.hh"
#include "../config/config.h"   // BST_VERSION
#include "bsemain.hh"
#include "bse/internal.hh"
#include <bse/bseapi_handles.hh>
#include <bse/bse.hh>           // init_server_connection

namespace Bse {

// == BSE Initialization ==

/** Create SFI glue layer context.
 * Create and push an SFI glue layer context for the calling thread, to enable communications with the
 * main BSE thread library.
 */
SfiGlueContext*
init_glue_context (const gchar *client, const std::function<void()> &caller_wakeup)
{
  return _bse_glue_context_create (client, caller_wakeup);
}

/** Initialize and start BSE.
 * Initialize the BSE library and start the main BSE thread. Arguments specific to BSE are removed
 * from @a argc / @a argv.
 */
void
init_async (int *argc, char **argv, const char *app_name, const StringVector &args)
{
  _bse_init_async (argc, argv, app_name, args);
}

/// Check wether init_async() still needs to be called.
bool
init_needed ()
{
  return _bse_initialized() == false;
}

// == TaskRegistry ==
static std::mutex         task_registry_mutex_;
static TaskRegistry::List task_registry_tasks_;

void
TaskRegistry::add (const std::string &name, int pid, int tid)
{
  Bse::TaskStatus task (pid, tid);
  task.name = name;
  task.update();
  std::lock_guard<std::mutex> locker (task_registry_mutex_);
  task_registry_tasks_.push_back (task);
}

bool
TaskRegistry::remove (int tid)
{
  std::lock_guard<std::mutex> locker (task_registry_mutex_);
  for (auto it = task_registry_tasks_.begin(); it != task_registry_tasks_.end(); it++)
    if (it->task_id == tid)
      {
        task_registry_tasks_.erase (it);
        return true;
      }
  return false;
}

void
TaskRegistry::update ()
{
  std::lock_guard<std::mutex> locker (task_registry_mutex_);
  for (auto &task : task_registry_tasks_)
    task.update();
}

TaskRegistry::List
TaskRegistry::list ()
{
  std::lock_guard<std::mutex> locker (task_registry_mutex_);
  return task_registry_tasks_;
}

class AidaGlibSourceImpl : public AidaGlibSource {
  static AidaGlibSourceImpl* self_         (GSource *src)                     { return (AidaGlibSourceImpl*) src; }
  static int                 glib_prepare  (GSource *src, int *timeoutp)      { return self_ (src)->prepare (timeoutp); }
  static int                 glib_check    (GSource *src)                     { return self_ (src)->check(); }
  static int                 glib_dispatch (GSource *src, GSourceFunc, void*) { return self_ (src)->dispatch(); }
  static void                glib_finalize (GSource *src)                     { self_ (src)->~AidaGlibSourceImpl(); }
  Aida::BaseConnection      *connection_;
  GPollFD                         pfd_;
  AidaGlibSourceImpl (Aida::BaseConnection *connection) :
    connection_ (connection), pfd_ { -1, 0, 0 }
  {
    pfd_.fd = connection_->notify_fd();
    pfd_.events = G_IO_IN;
    g_source_add_poll (this, &pfd_);
  }
  ~AidaGlibSourceImpl ()
  {
    g_source_remove_poll (this, &pfd_);
  }
  bool
  prepare (int *timeoutp)
  {
    return pfd_.revents || connection_->pending();
  }
  bool
  check ()
  {
    return pfd_.revents || connection_->pending();
  }
  bool
  dispatch ()
  {
    pfd_.revents = 0;
    connection_->dispatch();
    return true;
  }
public:
  static AidaGlibSourceImpl*
  create (Aida::BaseConnection *connection)
  {
    assert_return (connection != NULL, NULL);
    static GSourceFuncs glib_source_funcs = { glib_prepare, glib_check, glib_dispatch, glib_finalize, NULL, NULL };
    GSource *src = g_source_new (&glib_source_funcs, sizeof (AidaGlibSourceImpl));
    return new (src) AidaGlibSourceImpl (connection);
  }
};

AidaGlibSource*
AidaGlibSource::create (Aida::BaseConnection *connection)
{
  return AidaGlibSourceImpl::create (connection);
}

static Aida::ClientConnectionP *client_connection = NULL;

/// Retrieve a handle for the Bse::Server instance managing the Bse thread.
ServerHandle
init_server_instance () // bse.hh
{
  ServerH server;
  Aida::ClientConnectionP connection = init_server_connection();
  if (connection)
    server = connection->remote_origin<ServerH>();
  return server;
}

/// Retrieve the ClientConnection used for RPC communication with the Bse thread.
Aida::ClientConnectionP
init_server_connection () // bse.hh
{
  if (!client_connection)
    {
      Aida::ClientConnectionP connection = Aida::ClientConnection::connect ("inproc://BSE-" BST_VERSION);
      ServerH bseconnection_server_handle;
      if (connection)
        bseconnection_server_handle = connection->remote_origin<ServerH>(); // sets errno
      assert_return (bseconnection_server_handle != NULL, NULL);
      constexpr SfiProxy BSE_SERVER = 1;
      assert_return (bseconnection_server_handle.proxy_id() == BSE_SERVER, NULL);
      assert_return (bseconnection_server_handle.from_proxy (BSE_SERVER) == bseconnection_server_handle, NULL);
      assert_return (client_connection == NULL, NULL);
      client_connection = new Aida::ClientConnectionP (connection);
    }
  return *client_connection;
}

} // Bse

#include "bseapi_handles.cc"      // build IDL client interface
<commit_msg>BSE: bsestartup: fix Bse::version() usage<commit_after>// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
#include "bsestartup.hh"
#include "bsemain.hh"
#include "bse/internal.hh"
#include <bse/bseapi_handles.hh>
#include <bse/bse.hh>           // init_server_connection

namespace Bse {

// == BSE Initialization ==

/** Create SFI glue layer context.
 * Create and push an SFI glue layer context for the calling thread, to enable communications with the
 * main BSE thread library.
 */
SfiGlueContext*
init_glue_context (const gchar *client, const std::function<void()> &caller_wakeup)
{
  return _bse_glue_context_create (client, caller_wakeup);
}

/** Initialize and start BSE.
 * Initialize the BSE library and start the main BSE thread. Arguments specific to BSE are removed
 * from @a argc / @a argv.
 */
void
init_async (int *argc, char **argv, const char *app_name, const StringVector &args)
{
  _bse_init_async (argc, argv, app_name, args);
}

/// Check wether init_async() still needs to be called.
bool
init_needed ()
{
  return _bse_initialized() == false;
}

// == TaskRegistry ==
static std::mutex         task_registry_mutex_;
static TaskRegistry::List task_registry_tasks_;

void
TaskRegistry::add (const std::string &name, int pid, int tid)
{
  Bse::TaskStatus task (pid, tid);
  task.name = name;
  task.update();
  std::lock_guard<std::mutex> locker (task_registry_mutex_);
  task_registry_tasks_.push_back (task);
}

bool
TaskRegistry::remove (int tid)
{
  std::lock_guard<std::mutex> locker (task_registry_mutex_);
  for (auto it = task_registry_tasks_.begin(); it != task_registry_tasks_.end(); it++)
    if (it->task_id == tid)
      {
        task_registry_tasks_.erase (it);
        return true;
      }
  return false;
}

void
TaskRegistry::update ()
{
  std::lock_guard<std::mutex> locker (task_registry_mutex_);
  for (auto &task : task_registry_tasks_)
    task.update();
}

TaskRegistry::List
TaskRegistry::list ()
{
  std::lock_guard<std::mutex> locker (task_registry_mutex_);
  return task_registry_tasks_;
}

class AidaGlibSourceImpl : public AidaGlibSource {
  static AidaGlibSourceImpl* self_         (GSource *src)                     { return (AidaGlibSourceImpl*) src; }
  static int                 glib_prepare  (GSource *src, int *timeoutp)      { return self_ (src)->prepare (timeoutp); }
  static int                 glib_check    (GSource *src)                     { return self_ (src)->check(); }
  static int                 glib_dispatch (GSource *src, GSourceFunc, void*) { return self_ (src)->dispatch(); }
  static void                glib_finalize (GSource *src)                     { self_ (src)->~AidaGlibSourceImpl(); }
  Aida::BaseConnection      *connection_;
  GPollFD                         pfd_;
  AidaGlibSourceImpl (Aida::BaseConnection *connection) :
    connection_ (connection), pfd_ { -1, 0, 0 }
  {
    pfd_.fd = connection_->notify_fd();
    pfd_.events = G_IO_IN;
    g_source_add_poll (this, &pfd_);
  }
  ~AidaGlibSourceImpl ()
  {
    g_source_remove_poll (this, &pfd_);
  }
  bool
  prepare (int *timeoutp)
  {
    return pfd_.revents || connection_->pending();
  }
  bool
  check ()
  {
    return pfd_.revents || connection_->pending();
  }
  bool
  dispatch ()
  {
    pfd_.revents = 0;
    connection_->dispatch();
    return true;
  }
public:
  static AidaGlibSourceImpl*
  create (Aida::BaseConnection *connection)
  {
    assert_return (connection != NULL, NULL);
    static GSourceFuncs glib_source_funcs = { glib_prepare, glib_check, glib_dispatch, glib_finalize, NULL, NULL };
    GSource *src = g_source_new (&glib_source_funcs, sizeof (AidaGlibSourceImpl));
    return new (src) AidaGlibSourceImpl (connection);
  }
};

AidaGlibSource*
AidaGlibSource::create (Aida::BaseConnection *connection)
{
  return AidaGlibSourceImpl::create (connection);
}

static Aida::ClientConnectionP *client_connection = NULL;

/// Retrieve a handle for the Bse::Server instance managing the Bse thread.
ServerHandle
init_server_instance () // bse.hh
{
  ServerH server;
  Aida::ClientConnectionP connection = init_server_connection();
  if (connection)
    server = connection->remote_origin<ServerH>();
  return server;
}

/// Retrieve the ClientConnection used for RPC communication with the Bse thread.
Aida::ClientConnectionP
init_server_connection () // bse.hh
{
  if (!client_connection)
    {
      Aida::ClientConnectionP connection = Aida::ClientConnection::connect ("inproc://BSE-" + Bse::version());
      ServerH bseconnection_server_handle;
      if (connection)
        bseconnection_server_handle = connection->remote_origin<ServerH>(); // sets errno
      assert_return (bseconnection_server_handle != NULL, NULL);
      constexpr SfiProxy BSE_SERVER = 1;
      assert_return (bseconnection_server_handle.proxy_id() == BSE_SERVER, NULL);
      assert_return (bseconnection_server_handle.from_proxy (BSE_SERVER) == bseconnection_server_handle, NULL);
      assert_return (client_connection == NULL, NULL);
      client_connection = new Aida::ClientConnectionP (connection);
    }
  return *client_connection;
}

} // Bse

#include "bse/bseapi_handles.cc"        // build IDL client interface
<|endoftext|>


<commit_before>#pragma once

#include "constants.hpp"
#include "file_monitor.hpp"
#include "filesystem.hpp"
#include "gcd_utility.hpp"
#include "logger.hpp"
#include <fstream>

namespace krbn {
class grabber_alerts_monitor final {
public:
  typedef std::function<void(void)> callback;

  grabber_alerts_monitor(const grabber_alerts_monitor&) = delete;

  grabber_alerts_monitor(const callback& callback) : callback_(callback) {
    auto file_path = constants::get_grabber_alerts_json_file_path();
    auto directory = filesystem::dirname(file_path);

    std::vector<std::pair<std::string, std::vector<std::string>>> targets = {
        {directory, {file_path}},
    };
    file_monitor_ = std::make_unique<file_monitor>(targets,
                                                   [this](const std::string&) {
                                                     std::ifstream stream(constants::get_grabber_alerts_json_file_path());
                                                     if (stream) {
                                                       auto json = nlohmann::json::parse(stream);

                                                       // json example
                                                       //
                                                       // {
                                                       //     "alerts": [
                                                       //         "system_policy_prevents_loading_kext"
                                                       //     ]
                                                       // }

                                                       const std::string key = "alerts";
                                                       if (json.find(key) != std::end(json)) {
                                                         auto alerts = json[key];
                                                         if (alerts.is_array() && !alerts.empty()) {
                                                           auto s = json.dump();
                                                           if (json_string_ != s) {
                                                             json_string_ = s;
                                                             if (callback_) {
                                                               callback_();
                                                             }
                                                           }
                                                         }
                                                       }
                                                     }
                                                   });
  }

  ~grabber_alerts_monitor(void) {
    gcd_utility::dispatch_sync_in_main_queue(^{
      file_monitor_ = nullptr;
    });
  }

private:
  callback callback_;

  std::string json_string_;
  std::unique_ptr<file_monitor> file_monitor_;
};
} // namespace krbn
<commit_msg>catch json::parse error<commit_after>#pragma once

#include "constants.hpp"
#include "file_monitor.hpp"
#include "filesystem.hpp"
#include "gcd_utility.hpp"
#include "logger.hpp"
#include <fstream>

namespace krbn {
class grabber_alerts_monitor final {
public:
  typedef std::function<void(void)> callback;

  grabber_alerts_monitor(const grabber_alerts_monitor&) = delete;

  grabber_alerts_monitor(const callback& callback) : callback_(callback) {
    auto file_path = constants::get_grabber_alerts_json_file_path();
    auto directory = filesystem::dirname(file_path);

    std::vector<std::pair<std::string, std::vector<std::string>>> targets = {
        {directory, {file_path}},
    };
    file_monitor_ = std::make_unique<file_monitor>(targets,
                                                   [this](const std::string&) {
                                                     auto file_path = constants::get_grabber_alerts_json_file_path();
                                                     std::ifstream stream(file_path);
                                                     if (stream) {
                                                       try {
                                                         auto json = nlohmann::json::parse(stream);

                                                         // json example
                                                         //
                                                         // {
                                                         //     "alerts": [
                                                         //         "system_policy_prevents_loading_kext"
                                                         //     ]
                                                         // }

                                                         const std::string key = "alerts";
                                                         if (json.find(key) != std::end(json)) {
                                                           auto alerts = json[key];
                                                           if (alerts.is_array() && !alerts.empty()) {
                                                             auto s = json.dump();
                                                             if (json_string_ != s) {
                                                               json_string_ = s;
                                                               if (callback_) {
                                                                 callback_();
                                                               }
                                                             }
                                                           }
                                                         }
                                                       } catch (std::exception& e) {
                                                         logger::get_logger().error("parse error in {0}: {1}", file_path, e.what());
                                                       }
                                                     }
                                                   });
  }

  ~grabber_alerts_monitor(void) {
    gcd_utility::dispatch_sync_in_main_queue(^{
      file_monitor_ = nullptr;
    });
  }

private:
  callback callback_;

  std::string json_string_;
  std::unique_ptr<file_monitor> file_monitor_;
};
} // namespace krbn
<|endoftext|>


<commit_before>/*
* Copyright (c) 2006, Ondrej Danek (www.ondrej-danek.net)
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Ondrej Danek 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 OWNER 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 "Level.h"
#include "json/JsonParser.h"

namespace Duel6
{
	Level::Level(const std::string& path, bool mirror, const Block::Meta& blockMeta)
		: blockMeta(blockMeta)
	{
		load(path, mirror);
	}

	void Level::load(const std::string& path, bool mirror)
	{
		levelData.clear();
		waterLevel = 0;
		Json::Parser parser;
		Json::Value root = parser.parse(path);

		width = root.get("width").asInt();
		height = root.get("height").asInt();

		Int32 blockCount = width * height;
		Json::Value blocks = root.get("blocks");
		levelData.resize(blockCount);
		for (Size i = 0; i < blocks.getLength(); i++)
		{
			levelData[i] = blocks.get(i).asInt();
		}

		if (mirror)
		{
			mirrorLevelData();
		}
		waterBlock = findWaterType();
	}

	void Level::mirrorLevelData()
	{
		for (Int32 y = 0; y < height; y++)
		{
			for (Int32 x = 0; x < width / 2; x++)
			{
				std::swap(levelData[y * width + x], levelData[y * width + width - 1 - x]);
			}
		}
	}

	void Level::raiseWater()
	{
		if(waterLevel < getHeight() - 2)
		{
			waterLevel++;
			for(Int32 x = 1; x < getWidth() - 1; x++)
			{
				if(!isWall(x, waterLevel, false))
				{
					setBlock(waterBlock, x, waterLevel);
				}
			}
		}
	}

	Uint16 Level::findWaterType() const
	{
		for (Int32 y = 0; y < getHeight(); y++)
		{
			for (Int32 x = 0; x < getWidth(); x++)
			{
				if (isWater(x, y))
				{
					return getBlock(x, y);
				}
			}
		}

		static Uint16 waterBlocks[] = { 4, 16, 33 };
		return waterBlocks[rand() % 3];
	}

	Water::Type Level::getWaterType(Int32 x, Int32 y) const
	{
		if (isWater(x, y))
		{
			Uint16 block = getBlock(x, y);
			if (block == 4)
			{
				return Water::Type::Blue;
			}
			else if (block == 16)
			{
				return Water::Type::Red;
			}
			else if (block == 33)
			{
				return Water::Type::Green;
			}
		}

		return Water::Type::None;
	}
}<commit_msg>Fix water raising<commit_after>/*
* Copyright (c) 2006, Ondrej Danek (www.ondrej-danek.net)
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Ondrej Danek 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 OWNER 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 "Level.h"
#include "json/JsonParser.h"

namespace Duel6
{
	Level::Level(const std::string& path, bool mirror, const Block::Meta& blockMeta)
		: blockMeta(blockMeta)
	{
		load(path, mirror);
	}

	void Level::load(const std::string& path, bool mirror)
	{
		levelData.clear();
		waterLevel = 0;
		Json::Parser parser;
		Json::Value root = parser.parse(path);

		width = root.get("width").asInt();
		height = root.get("height").asInt();

		Int32 blockCount = width * height;
		Json::Value blocks = root.get("blocks");
		levelData.resize(blockCount);
		for (Size i = 0; i < blocks.getLength(); i++)
		{
			levelData[i] = blocks.get(i).asInt();
		}

		if (mirror)
		{
			mirrorLevelData();
		}
		waterBlock = findWaterType();
	}

	void Level::mirrorLevelData()
	{
		for (Int32 y = 0; y < height; y++)
		{
			for (Int32 x = 0; x < width / 2; x++)
			{
				std::swap(levelData[y * width + x], levelData[y * width + width - 1 - x]);
			}
		}
	}

	void Level::raiseWater()
	{
		if(waterLevel < getHeight() - 1)
		{
			waterLevel++;
			for(Int32 x = 0; x < getWidth(); x++)
			{
				if(!isWall(x, waterLevel, false))
				{
					setBlock(waterBlock, x, waterLevel);
				}
			}
		}
	}

	Uint16 Level::findWaterType() const
	{
		for (Int32 y = 0; y < getHeight(); y++)
		{
			for (Int32 x = 0; x < getWidth(); x++)
			{
				if (isWater(x, y))
				{
					return getBlock(x, y);
				}
			}
		}

		static Uint16 waterBlocks[] = { 4, 16, 33 };
		return waterBlocks[rand() % 3];
	}

	Water::Type Level::getWaterType(Int32 x, Int32 y) const
	{
		if (isWater(x, y))
		{
			Uint16 block = getBlock(x, y);
			if (block == 4)
			{
				return Water::Type::Blue;
			}
			else if (block == 16)
			{
				return Water::Type::Red;
			}
			else if (block == 33)
			{
				return Water::Type::Green;
			}
		}

		return Water::Type::None;
	}
}<|endoftext|>


<commit_before>#include "HdmiDisplay.h"

HdmiDisplayIndications::HdmiDisplayIndications()
{
}
HdmiDisplayIndications::~HdmiDisplayIndications()
{
}

struct HdmiDisplayIndicationsvsyncMSG : public PortalMessage
{
//fix Adapter.bsv to unreverse these
        unsigned long long v:64;

};

void HdmiDisplayIndications::handleMessage(PortalMessage *msg)
{
    switch (msg->channel) {
    case 0: vsync(((HdmiDisplayIndicationsvsyncMSG *)msg)->v); break;

    default: break;
    }
}

HdmiDisplay *HdmiDisplay::createHdmiDisplay(const char *instanceName, HdmiDisplayIndications *indications)
{
    HdmiDisplay *instance = new HdmiDisplay(instanceName, indications);
    return instance;
}

HdmiDisplay::HdmiDisplay(const char *instanceName, HdmiDisplayIndications *indications)
 : PortalInstance(instanceName, indications)
{
}
HdmiDisplay::~HdmiDisplay()
{
    close();
}

struct HdmiDisplaysetPatternRegMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long yuv422;

    } request;
};

void HdmiDisplay::setPatternReg ( unsigned long yuv422 )
{
    HdmiDisplaysetPatternRegMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 0;
    msg.request.yuv422 = yuv422;

    sendMessage(&msg);
};

struct HdmiDisplaystartFrameBuffer0MSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long base;

    } request;
};

void HdmiDisplay::startFrameBuffer0 ( unsigned long base )
{
    HdmiDisplaystartFrameBuffer0MSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 1;
    msg.request.base = base;

    sendMessage(&msg);
};

struct HdmiDisplaystartFrameBuffer1MSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long base;

    } request;
};

void HdmiDisplay::startFrameBuffer1 ( unsigned long base )
{
    HdmiDisplaystartFrameBuffer1MSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 2;
    msg.request.base = base;

    sendMessage(&msg);
};

struct HdmiDisplaywaitForVsyncMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long unused;

    } request;
};

void HdmiDisplay::waitForVsync ( unsigned long unused )
{
    HdmiDisplaywaitForVsyncMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 3;
    msg.request.unused = unused;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiLinesPixelsMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiLinesPixels ( unsigned long value )
{
    HdmiDisplayhdmiLinesPixelsMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 4;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiBlankLinesPixelsMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiBlankLinesPixels ( unsigned long value )
{
    HdmiDisplayhdmiBlankLinesPixelsMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 5;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiStrideBytesMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long strideBytes;

    } request;
};

void HdmiDisplay::hdmiStrideBytes ( unsigned long strideBytes )
{
    HdmiDisplayhdmiStrideBytesMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 6;
    msg.request.strideBytes = strideBytes;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiLineCountMinMaxMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiLineCountMinMax ( unsigned long value )
{
    HdmiDisplayhdmiLineCountMinMaxMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 7;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiPixelCountMinMaxMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiPixelCountMinMax ( unsigned long value )
{
    HdmiDisplayhdmiPixelCountMinMaxMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 8;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiSyncWidthsMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiSyncWidths ( unsigned long value )
{
    HdmiDisplayhdmiSyncWidthsMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 9;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplaybeginTranslationTableMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long index:8;

    } request;
};

void HdmiDisplay::beginTranslationTable ( unsigned long index )
{
    HdmiDisplaybeginTranslationTableMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 10;
    msg.request.index = index;

    sendMessage(&msg);
};

struct HdmiDisplayaddTranslationEntryMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long length:12;
        unsigned long address:20;

    } request;
};

void HdmiDisplay::addTranslationEntry ( unsigned long address, unsigned long length )
{
    HdmiDisplayaddTranslationEntryMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 11;
    msg.request.address = address;
    msg.request.length = length;

    sendMessage(&msg);
};
<commit_msg>updated HdmiDisplay.cpp<commit_after>#include "HdmiDisplay.h"

HdmiDisplayIndications::HdmiDisplayIndications()
{
}
HdmiDisplayIndications::~HdmiDisplayIndications()
{
}

struct HdmiDisplayIndicationsvsyncMSG : public PortalMessage
{
//fix Adapter.bsv to unreverse these
        unsigned long long v:64;

};

void HdmiDisplayIndications::handleMessage(PortalMessage *msg)
{
    switch (msg->channel) {
    case 12: vsync(((HdmiDisplayIndicationsvsyncMSG *)msg)->v); break;

    default: break;
    }
}

HdmiDisplay *HdmiDisplay::createHdmiDisplay(const char *instanceName, HdmiDisplayIndications *indications)
{
    HdmiDisplay *instance = new HdmiDisplay(instanceName, indications);
    return instance;
}

HdmiDisplay::HdmiDisplay(const char *instanceName, HdmiDisplayIndications *indications)
 : PortalInstance(instanceName, indications)
{
}
HdmiDisplay::~HdmiDisplay()
{
    close();
}

struct HdmiDisplaysetPatternRegMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long yuv422;

    } request;
};

void HdmiDisplay::setPatternReg ( unsigned long yuv422 )
{
    HdmiDisplaysetPatternRegMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 0;
    msg.request.yuv422 = yuv422;

    sendMessage(&msg);
};

struct HdmiDisplaystartFrameBuffer0MSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long base;

    } request;
};

void HdmiDisplay::startFrameBuffer0 ( unsigned long base )
{
    HdmiDisplaystartFrameBuffer0MSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 1;
    msg.request.base = base;

    sendMessage(&msg);
};

struct HdmiDisplaystartFrameBuffer1MSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long base;

    } request;
};

void HdmiDisplay::startFrameBuffer1 ( unsigned long base )
{
    HdmiDisplaystartFrameBuffer1MSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 2;
    msg.request.base = base;

    sendMessage(&msg);
};

struct HdmiDisplaywaitForVsyncMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long unused;

    } request;
};

void HdmiDisplay::waitForVsync ( unsigned long unused )
{
    HdmiDisplaywaitForVsyncMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 3;
    msg.request.unused = unused;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiLinesPixelsMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiLinesPixels ( unsigned long value )
{
    HdmiDisplayhdmiLinesPixelsMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 4;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiBlankLinesPixelsMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiBlankLinesPixels ( unsigned long value )
{
    HdmiDisplayhdmiBlankLinesPixelsMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 5;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiStrideBytesMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long strideBytes;

    } request;
};

void HdmiDisplay::hdmiStrideBytes ( unsigned long strideBytes )
{
    HdmiDisplayhdmiStrideBytesMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 6;
    msg.request.strideBytes = strideBytes;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiLineCountMinMaxMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiLineCountMinMax ( unsigned long value )
{
    HdmiDisplayhdmiLineCountMinMaxMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 7;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiPixelCountMinMaxMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiPixelCountMinMax ( unsigned long value )
{
    HdmiDisplayhdmiPixelCountMinMaxMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 8;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplayhdmiSyncWidthsMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long value;

    } request;
};

void HdmiDisplay::hdmiSyncWidths ( unsigned long value )
{
    HdmiDisplayhdmiSyncWidthsMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 9;
    msg.request.value = value;

    sendMessage(&msg);
};

struct HdmiDisplaybeginTranslationTableMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long index:8;

    } request;
};

void HdmiDisplay::beginTranslationTable ( unsigned long index )
{
    HdmiDisplaybeginTranslationTableMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 10;
    msg.request.index = index;

    sendMessage(&msg);
};

struct HdmiDisplayaddTranslationEntryMSG : public PortalMessage
{
    struct Request {
    //fix Adapter.bsv to unreverse these
        unsigned long length:12;
        unsigned long address:20;

    } request;
};

void HdmiDisplay::addTranslationEntry ( unsigned long address, unsigned long length )
{
    HdmiDisplayaddTranslationEntryMSG msg;
    msg.size = sizeof(msg.request);
    msg.channel = 11;
    msg.request.address = address;
    msg.request.length = length;

    sendMessage(&msg);
};
<|endoftext|>


<commit_before>#include "library/sp.h"
#include "game/apocresources/loftemps.h"
#include "framework/logger.h"
#include "framework/data.h"

namespace OpenApoc
{

LOFTemps::LOFTemps(IFile &datFile, IFile &tabFile)
{
	if (!tabFile)
	{
		LogError("Invalid TAB file");
		return;
	}

	if (!datFile)
	{
		LogError("Invalid DAT file");
		return;
	}

	uint32_t offset;
	while (tabFile.readule32(offset))
	{
		datFile.seekg(offset * 4, std::ios::beg);
		if (!datFile)
		{
			LogError("Seeking beyond end of file reading offset %u", offset * 4);
			return;
		}

		uint32_t width;
		if (!datFile.readule32(width))
		{
			LogError("Failed to read width");
			return;
		}
		uint32_t height;
		if (!datFile.readule32(height))
		{
			LogError("Failed to read height");
			return;
		}

		if (width % 8)
		{
			LogError("Non-8-bit-aligned width: %u", width);
			return;
		}

		auto slice = std::make_shared<VoxelSlice>(Vec2<int>{width, height});

		for (unsigned int y = 0; y < height; y++)
		{
			// Bitmasks are packed into a 32-bit word, so all strides will
			// be 4-byte aligned
			for (unsigned int x = 0; x < width; x += 32)
			{
				uint32_t bitmask;
				if (!datFile.readule32(bitmask))
				{
					LogError("Failed to read bitmask at {%u,%u}", x, y);
					return;
				}
				for (unsigned int bit = 0; bit < 32; bit++)
				{
					if (x >= width)
						break;
					bool b;
					if (bitmask & 0x80000000)
						b = true;
					else
						b = false;
					bitmask >>= 1;
					slice->setBit(Vec2<int>{x + bit, y}, b);
				}
			}
		}
		LogInfo("Read voxel slice of size {%u,%u}", width, height);
		this->slices.push_back(slice);
	}
}

sp<VoxelSlice> LOFTemps::getSlice(unsigned int idx)
{
	if (idx >= this->slices.size())
	{
		LogError("Requested slice %d - only %u in file", idx, this->slices.size());
		return nullptr;
	}
	return this->slices[idx];
}

}; // namespace OpenApoc
<commit_msg>Fix collisions<commit_after>#include "library/sp.h"
#include "game/apocresources/loftemps.h"
#include "framework/logger.h"
#include "framework/data.h"

namespace OpenApoc
{

LOFTemps::LOFTemps(IFile &datFile, IFile &tabFile)
{
	if (!tabFile)
	{
		LogError("Invalid TAB file");
		return;
	}

	if (!datFile)
	{
		LogError("Invalid DAT file");
		return;
	}

	uint32_t offset;
	while (tabFile.readule32(offset))
	{
		datFile.seekg(offset * 4, std::ios::beg);
		if (!datFile)
		{
			LogError("Seeking beyond end of file reading offset %u", offset * 4);
			return;
		}

		uint32_t width;
		if (!datFile.readule32(width))
		{
			LogError("Failed to read width");
			return;
		}
		uint32_t height;
		if (!datFile.readule32(height))
		{
			LogError("Failed to read height");
			return;
		}

		if (width % 8)
		{
			LogError("Non-8-bit-aligned width: %u", width);
			return;
		}

		auto slice = std::make_shared<VoxelSlice>(Vec2<int>{width, height});

		for (unsigned int y = 0; y < height; y++)
		{
			// Bitmasks are packed into a 32-bit word, so all strides will
			// be 4-byte aligned
			for (unsigned int x = 0; x < width; x += 32)
			{
				uint32_t bitmask;
				if (!datFile.readule32(bitmask))
				{
					LogError("Failed to read bitmask at {%u,%u}", x, y);
					return;
				}
				for (unsigned int bit = 0; bit < 32; bit++)
				{
					if (x >= width)
						break;
					bool b;
					if (bitmask & 0x80000000)
						b = true;
					else
						b = false;
					bitmask <<= 1;
					slice->setBit(Vec2<int>{x + bit, y}, b);
				}
			}
		}
		LogInfo("Read voxel slice of size {%u,%u}", width, height);
		this->slices.push_back(slice);
	}
}

sp<VoxelSlice> LOFTemps::getSlice(unsigned int idx)
{
	if (idx >= this->slices.size())
	{
		LogError("Requested slice %d - only %u in file", idx, this->slices.size());
		return nullptr;
	}
	return this->slices[idx];
}

}; // namespace OpenApoc
<|endoftext|>


<commit_before>/* Copyright (c) 2013 Fabian Schuiki */
#pragma once
#include "../math.hpp"
#include "../matrix.hpp"
#define GAMMA_HAS_TRANSFORM_PERSPECTIVE

namespace gamma {
namespace transform {

/** A perspective projection, as it would be generated by the gluPerspective
 * OpenGL call. Note that the field-of-view is vertical, aspect is the ratio
 * between the horizontal and vertical field-of-view, and near and far refer to
 * the near and far clipping planes. */
template <typename T> struct perspective
{
	typedef perspective<T> self;
	typedef T scalar_type;
	typedef matrix4<T> matrix_type;

	const T fov; // vertical field of view [radians]
	const T aspect;
	const T near, far; // clipping planes

	perspective(): m(1) {}
	perspective(T fov, T aspect, T near, T far): fov(fov), aspect(aspect), near(near), far(far)
	{
		T f = tan(M_PI_2 - fov/2); // cot(x) = tan(pi/2 - x)
		T g = f/aspect;
		T a = near+far;
		T b = near-far;
		T c = 2*near*far;
		m = matrix_type(
			g,  0,    0,    0,
			0,  f,    0,    0,
			0,  0,  a/b,  c/b,
			0,  0,   -1,    0
		);
	}

	operator matrix_type() const { return m; }

protected:
	matrix_type m;
};

typedef perspective<float>  perspectivef;
typedef perspective<double> perspectived;

} // namespace transform
} // namespace gamma<commit_msg>fixed: perspective now follows gluPerspective<commit_after>/* Copyright (c) 2013 Fabian Schuiki */
#pragma once
#include "../math.hpp"
#include "../matrix.hpp"
#define GAMMA_HAS_TRANSFORM_PERSPECTIVE

namespace gamma {
namespace transform {

/** A perspective projection, as it would be generated by the gluPerspective
 * OpenGL call. Note that the field-of-view is vertical, aspect is the ratio
 * between the horizontal and vertical field-of-view, and near and far refer to
 * the near and far clipping planes. */
template <typename T> struct perspective
{
	typedef perspective<T> self;
	typedef T scalar_type;
	typedef matrix4<T> matrix_type;

	const T fov; // vertical field of view [radians]
	const T aspect;
	const T near, far; // clipping planes

	perspective(): m(1) {}
	perspective(T fov, T aspect, T near, T far): fov(fov), aspect(aspect), near(near), far(far)
	{
		T f = tan(M_PI_2 - fov/2); // cot(x) = tan(pi/2 - x)
		T g = f/aspect;
		T a = far+near;
		T b = far-near;
		T c = 2*near*far;
		m = matrix_type(
			g,  0,    0,    0,
			0,  f,    0,    0,
			0,  0, -a/b, -c/b,
			0,  0,   -1,    0
		);
	}

	operator matrix_type() const { return m; }

protected:
	matrix_type m;
};

typedef perspective<float>  perspectivef;
typedef perspective<double> perspectived;

} // namespace transform
} // namespace gamma<|endoftext|>


<commit_before>#if defined(__linux__) || defined(__APPLE__)
#include <unistd.h>
#include <syslog.h>

#include "dobby_internal.h"

#include "Interceptor.h"

__attribute__((constructor)) static void ctor() {
  DLOG(-1, "================================");
  DLOG(-1, "Dobby");
  DLOG(-1, "================================");

  DLOG(-1, "dobby in debug log mode, disable with cmake flag \"-DDOBBY_DEBUG=OFF\"");
}

PUBLIC const char *DobbyBuildVersion() {
  return __DOBBY_BUILD_VERSION__;
}

PUBLIC int DobbyDestroy(void *address) {
  Interceptor *interceptor = Interceptor::SharedInstance();

  // check if we already hook
  HookEntry *entry = interceptor->FindHookEntry(address);
  if (entry) {
    uint8_t *buffer      = entry->origin_chunk_.chunk_buffer;
    uint32_t buffer_size = entry->origin_chunk_.chunk.length;
#if defined(TARGET_ARCH_ARM)
    address = (void *)((addr_t)address - 1);
#endif
    CodePatch(address, buffer, buffer_size);
    return RT_SUCCESS;
  }

  return RT_FAILED;
}

#endif<commit_msg>[misc] update<commit_after>#if defined(__linux__) || defined(__APPLE__)
#include <unistd.h>
#include <syslog.h>

#include "dobby_internal.h"

#include "Interceptor.h"

__attribute__((constructor)) static void ctor() {
  DLOG(-1, "================================");
  DLOG(-1, "Dobby");
  DLOG(-1, "================================");

  DLOG(-1, "dobby in debug log mode, disable with cmake flag \"-DDOBBY_DEBUG=OFF\"");
}

PUBLIC const char *DobbyBuildVersion() {
  return __DOBBY_BUILD_VERSION__;
}

PUBLIC int DobbyDestroy(void *address) {
  // check if we already hook
  HookEntry *entry = Interceptor::SharedInstance()->FindHookEntry(address);
  if (entry) {
    uint8_t *buffer      = entry->origin_chunk_.chunk_buffer;
    uint32_t buffer_size = entry->origin_chunk_.chunk.length;
#if defined(TARGET_ARCH_ARM)
    address = (void *)((addr_t)address - 1);
#endif
    CodePatch(address, buffer, buffer_size);
    Interceptor::SharedInstance()->RemoveHookEntry(address);
    return RT_SUCCESS;
  }

  return RT_FAILED;
}

#endif<|endoftext|>


<commit_before>/*
Copyright (c) 2014, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

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

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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(S) 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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <cstring>

#include <iostream>
#include <sstream>

#include <llamaos/xen/Hypervisor.h>
#include <llamaos/xen/Shared_memory.h>
#include <llamaos/llamaOS.h>

using std::cout;
using std::endl;
using std::string;
using std::istringstream;
using std::vector;

using namespace llamaos;
using llamaos::xen::Hypervisor;
using llamaos::xen::Shared_memory;
using llamaos::xen::Shared_memory_creator;
using llamaos::xen::Shared_memory_user;

// static const int SHARED_PAGES = 6080;
// static const int SHARED_PAGES = 4096;
static const int SHARED_PAGES = 2048;

// static const int MAX_ENTRIES = 31; // NEED MORE !!!!
static const int MAX_ENTRIES = 28;
// static const int MAX_ENTRIES = 48;
static const int MAX_NAME = 55;
static const int MAX_ALIAS = 47;

#pragma pack(1)
typedef struct
{
   uint8_t name [MAX_NAME+1];
   uint8_t alias [MAX_ALIAS+1];
   uint64_t lock;
   uint64_t lock2;
   uint64_t offset;
   uint64_t size;

} directory_entry_t;

typedef struct
{
   uint64_t nodes;
   uint64_t barrier_count;
   bool barrier_sense;

   uint64_t next_offset;

   directory_entry_t entries [MAX_ENTRIES];

} directory_t;
#pragma pack()

Shared_memory *Shared_memory::create (const std::string &name, domid_t domid)
{
   // check if resource node
   size_t pos = name.find("-r.");

   if (pos != string::npos)
   {
      istringstream s(name.substr(pos+3));
      int nodes;
      s >> nodes;

      return new Shared_memory_creator (domid, nodes);
   }

   pos = name.find("-");

   if (pos != string::npos)
   {
      istringstream s(name.substr(pos+1));
      int node;
      s >> node;

      return new Shared_memory_user (domid, node);
   }

   return nullptr;
}

Shared_memory::Shared_memory ()
   :  barrier_sense(false)
{

}

Shared_memory::~Shared_memory ()
{

}

int Shared_memory::open (const std::string &name) const
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
//      cout << "opening " << name << endl;

      for (int i = 0; i < MAX_ENTRIES; i++)
      {
//         cout << "   [" << i << "] " << directory->entries [i].name << endl;

         // if (__sync_lock_test_and_set(&directory->entries [i].lock, 1) == 0)
         if (__sync_fetch_and_add(&directory->entries [i].lock, 1) == 0)
         {
            cout << "   writing to entry " << i << ", " << name.c_str () << endl;
            strncpy(reinterpret_cast<char *>(directory->entries [i].name), name.c_str (), MAX_NAME);
            wmb();
            return i + 200;
         }

//         cout << "   searching in entry " << i << endl;

         while (directory->entries [i].name [0] == '\0')
         {
            cout << "   open waiting for entry name to be written: " << i << endl;
            mb();
         }

         if (strncmp(name.c_str(), reinterpret_cast<const char *>(directory->entries [i].name), MAX_NAME) == 0)
         {
//            cout << "   found in entry " << i << endl;
            return i + 200;
         }
      }
   }

   return -1;
}

void *Shared_memory::map (int fd, uint64_t size) const
{
   uint8_t *pointer = get_pointer ();
   directory_t *directory = reinterpret_cast<directory_t *>(pointer);

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      cout << "mapping fd " << fd << ", size " << size << endl;
      int index = fd - 200;
      // uint64_t offset = PAGE_SIZE;

      if (__sync_fetch_and_add(&directory->entries [index].lock2, 1) == 0)
      {
         uint64_t offset = __sync_fetch_and_add(&directory->next_offset, size);

         directory->entries [index].offset = offset;
         directory->entries [index].size = size;
         wmb();
      }

      while (directory->entries [index].offset == 0)
      {
         cout << "   map waiting for entry offset to be written..." << index << endl;
         mb();
      }

      // for (int i = 0; i < index; i++)
      // {
      //    offset += directory->entries [i].size;
      // }

      // directory->entries [index].offset = offset;

      if ((directory->entries [index].offset + size) > (SHARED_PAGES * PAGE_SIZE))
      {
         cout << "exceeded shared memory space!!!!!" << endl;
         // throw
         for (;;);
         return nullptr;
      }

      cout << "     mapped to offset " << directory->entries [index].offset << endl;
      return pointer + directory->entries [index].offset;
   }

   return nullptr;
}

void Shared_memory::unmap (int ) const
{

}

void *Shared_memory::get (int fd) const
{
   uint8_t *pointer = get_pointer ();
   directory_t *directory = reinterpret_cast<directory_t *>(pointer);

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      return pointer + directory->entries [fd - 200].offset;
   }

   return nullptr;
}

int Shared_memory::get_size () const
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      for (int i = 0; i < MAX_ENTRIES; i++)
      {
         if (!directory->entries [i].lock)
         {
            return i;
         }
      }

      return MAX_ENTRIES;
   }

   return 0;
}

vector<string> Shared_memory::get_names () const
{
   vector<string> names;
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      for (int i = 0; i < MAX_ENTRIES; i++)
      {
//         if (directory->entries [i].name [0] == '\0')
//         {
//            break;
//         }

         if (!directory->entries [i].lock)
         {
            break;
         }

         while (directory->entries [i].name [0] == '\0')
         {
            cout << "   get_names waiting for entry to be written..." << i << endl;
            mb();
         }

         names.push_back (reinterpret_cast<const char *>(directory->entries [i].name));
      }
   }

   return names;
}

void Shared_memory::put_alias (const string &name, const string &alias) const
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      for (int i = 0; i < MAX_ENTRIES; i++)
      {
//         if (directory->entries [i].name [0] == '\0')
//         {
//            break;
//         }
         if (!directory->entries [i].lock)
         {
            break;
         }

         while (directory->entries [i].name [0] == '\0')
         {
            cout << "   put_alias waiting for entry name to be written..." << i << endl;
            mb();
         }

         if (strncmp(name.c_str(), reinterpret_cast<const char *>(directory->entries [i].name), MAX_NAME) == 0)
         {
            strncpy(reinterpret_cast<char *>(directory->entries [i].alias), alias.c_str (), MAX_ALIAS);
            break;
         }
      }
   }
}

string Shared_memory::get_name (const string &alias) const
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      for (int i = 0; i < MAX_ENTRIES; i++)
      {
//         if (directory->entries [i].name [0] == '\0')
//         {
//            break;
//         }
         if (!directory->entries [i].lock)
         {
            break;
         }

         while (directory->entries [i].alias [0] == '\0')
         {
            cout << "   get_name waiting for entry alias to be written..." << i << endl;
            mb();
         }

         if (strncmp(alias.c_str(), reinterpret_cast<const char *>(directory->entries [i].alias), MAX_ALIAS) == 0)
         {
            return reinterpret_cast<const char *>(directory->entries [i].name);
         }
      }
   }

   return "name not found";
}

void Shared_memory::barrier ()
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());
//   cout << "nodes: " << directory->nodes << endl;

   barrier_sense ^= true;

   if (__sync_sub_and_fetch (&directory->barrier_count, 1) == 0)
   {
      cout << "resetting barrier..." << endl;
         cout << "barrier: " << directory->barrier_count
              << ", " << directory->barrier_sense
              << ", " << barrier_sense << endl;
   cout << "nodes: " << directory->nodes << endl;

      directory->barrier_count = directory->nodes;
      wmb();

      directory->barrier_sense = barrier_sense;
         cout << "barrier: " << directory->barrier_count
              << ", " << directory->barrier_sense
              << ", " << barrier_sense << endl;
   cout << "nodes: " << directory->nodes << endl;
   }
   else
   {
         cout << "barrier: " << directory->barrier_count
              << ", " << directory->barrier_sense
              << ", " << barrier_sense << endl;
   cout << "nodes: " << directory->nodes << endl;
      while (barrier_sense != directory->barrier_sense)
      {
         mb();
      }
         cout << "barrier: " << directory->barrier_count
              << ", " << directory->barrier_sense
              << ", " << barrier_sense << endl;
   cout << "nodes: " << directory->nodes << endl;
   }
}

static uint8_t *create_pointer (domid_t domid, int nodes)
{
   Hypervisor *hypervisor = Hypervisor::get_instance ();

   const unsigned int size = SHARED_PAGES * PAGE_SIZE;
   uint8_t *pointer = static_cast<uint8_t *>(aligned_alloc (PAGE_SIZE, size));
   memset(static_cast<void *>(pointer), 0, size);

   for (int i = 0; i < nodes; i++)
   {
      for (int j = 0; j < SHARED_PAGES; j++)
      {
         hypervisor->grant_table.grant_access (domid + 1 + i, &pointer [j * PAGE_SIZE]);
      }
   }

   return pointer;
}

Shared_memory_creator::Shared_memory_creator (domid_t domid, int nodes)
   : pointer(create_pointer(domid, nodes))
{
   directory_t *directory = reinterpret_cast<directory_t *>(pointer);

   directory->nodes = nodes;
   directory->barrier_count = nodes;
   directory->barrier_sense = false;

   directory->next_offset = 2 * PAGE_SIZE;

//   cout << "nodes: " << directory->nodes << endl;
}

Shared_memory_creator::~Shared_memory_creator ()
{
   delete pointer;
}

uint8_t *Shared_memory_creator::get_pointer () const
{
   return pointer;
}

Shared_memory_user::Shared_memory_user (domid_t domid, int node)
   : grant_map(domid-1-node, (node * SHARED_PAGES), SHARED_PAGES)
//   : grant_map(domid-1-node, 49151 - (node * SHARED_PAGES), SHARED_PAGES)
//   : grant_map(domid-1-node, 32767 - (node * SHARED_PAGES), SHARED_PAGES)
//   : grant_map(domid-1-node, 16383 - (node * SHARED_PAGES), SHARED_PAGES)
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   cout << "nodes: " << directory->nodes << endl;
}

uint8_t *Shared_memory_user::get_pointer () const
{
   return reinterpret_cast<uint8_t *>(grant_map.get_pointer ());
}
<commit_msg>temp commit, force shared memory to 96 grant frame size<commit_after>/*
Copyright (c) 2014, William Magato
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

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

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) 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(S) 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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the copyright holder(s) or contributors.
*/

#include <cstring>

#include <iostream>
#include <sstream>

#include <llamaos/xen/Hypervisor.h>
#include <llamaos/xen/Shared_memory.h>
#include <llamaos/llamaOS.h>

using std::cout;
using std::endl;
using std::string;
using std::istringstream;
using std::vector;

using namespace llamaos;
using llamaos::xen::Hypervisor;
using llamaos::xen::Shared_memory;
using llamaos::xen::Shared_memory_creator;
using llamaos::xen::Shared_memory_user;

// !BAM TEMP - this will not work on default xen config
static const int SHARED_PAGES = 6080;
// static const int SHARED_PAGES = 4096;
// static const int SHARED_PAGES = 2048;

// static const int MAX_ENTRIES = 31; // NEED MORE !!!!
// static const int MAX_ENTRIES = 28;
static const int MAX_ENTRIES = 48;
static const int MAX_NAME = 55;
static const int MAX_ALIAS = 47;

#pragma pack(1)
typedef struct
{
   uint8_t name [MAX_NAME+1];
   uint8_t alias [MAX_ALIAS+1];
   uint64_t lock;
   uint64_t lock2;
   uint64_t offset;
   uint64_t size;

} directory_entry_t;

typedef struct
{
   uint64_t nodes;
   uint64_t barrier_count;
   bool barrier_sense;

   uint64_t next_offset;

   directory_entry_t entries [MAX_ENTRIES];

} directory_t;
#pragma pack()

Shared_memory *Shared_memory::create (const std::string &name, domid_t domid)
{
   // check if resource node
   size_t pos = name.find("-r.");

   if (pos != string::npos)
   {
      istringstream s(name.substr(pos+3));
      int nodes;
      s >> nodes;

      return new Shared_memory_creator (domid, nodes);
   }

   pos = name.find("-");

   if (pos != string::npos)
   {
      istringstream s(name.substr(pos+1));
      int node;
      s >> node;

      return new Shared_memory_user (domid, node);
   }

   return nullptr;
}

Shared_memory::Shared_memory ()
   :  barrier_sense(false)
{

}

Shared_memory::~Shared_memory ()
{

}

int Shared_memory::open (const std::string &name) const
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
//      cout << "opening " << name << endl;

      for (int i = 0; i < MAX_ENTRIES; i++)
      {
//         cout << "   [" << i << "] " << directory->entries [i].name << endl;

         // if (__sync_lock_test_and_set(&directory->entries [i].lock, 1) == 0)
         if (__sync_fetch_and_add(&directory->entries [i].lock, 1) == 0)
         {
            cout << "   writing to entry " << i << ", " << name.c_str () << endl;
            strncpy(reinterpret_cast<char *>(directory->entries [i].name), name.c_str (), MAX_NAME);
            wmb();
            return i + 200;
         }

//         cout << "   searching in entry " << i << endl;

         while (directory->entries [i].name [0] == '\0')
         {
            cout << "   open waiting for entry name to be written: " << i << endl;
            mb();
         }

         if (strncmp(name.c_str(), reinterpret_cast<const char *>(directory->entries [i].name), MAX_NAME) == 0)
         {
//            cout << "   found in entry " << i << endl;
            return i + 200;
         }
      }
   }

   return -1;
}

void *Shared_memory::map (int fd, uint64_t size) const
{
   uint8_t *pointer = get_pointer ();
   directory_t *directory = reinterpret_cast<directory_t *>(pointer);

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      cout << "mapping fd " << fd << ", size " << size << endl;
      int index = fd - 200;
      // uint64_t offset = PAGE_SIZE;

      if (__sync_fetch_and_add(&directory->entries [index].lock2, 1) == 0)
      {
         uint64_t offset = __sync_fetch_and_add(&directory->next_offset, size);

         directory->entries [index].offset = offset;
         directory->entries [index].size = size;
         wmb();
      }

      while (directory->entries [index].offset == 0)
      {
         cout << "   map waiting for entry offset to be written..." << index << endl;
         mb();
      }

      // for (int i = 0; i < index; i++)
      // {
      //    offset += directory->entries [i].size;
      // }

      // directory->entries [index].offset = offset;

      if ((directory->entries [index].offset + size) > (SHARED_PAGES * PAGE_SIZE))
      {
         cout << "exceeded shared memory space!!!!!" << endl;
         // throw
         for (;;);
         return nullptr;
      }

      cout << "     mapped to offset " << directory->entries [index].offset << endl;
      return pointer + directory->entries [index].offset;
   }

   return nullptr;
}

void Shared_memory::unmap (int ) const
{

}

void *Shared_memory::get (int fd) const
{
   uint8_t *pointer = get_pointer ();
   directory_t *directory = reinterpret_cast<directory_t *>(pointer);

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      return pointer + directory->entries [fd - 200].offset;
   }

   return nullptr;
}

int Shared_memory::get_size () const
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      for (int i = 0; i < MAX_ENTRIES; i++)
      {
         if (!directory->entries [i].lock)
         {
            return i;
         }
      }

      return MAX_ENTRIES;
   }

   return 0;
}

vector<string> Shared_memory::get_names () const
{
   vector<string> names;
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      for (int i = 0; i < MAX_ENTRIES; i++)
      {
//         if (directory->entries [i].name [0] == '\0')
//         {
//            break;
//         }

         if (!directory->entries [i].lock)
         {
            break;
         }

         while (directory->entries [i].name [0] == '\0')
         {
            cout << "   get_names waiting for entry to be written..." << i << endl;
            mb();
         }

         names.push_back (reinterpret_cast<const char *>(directory->entries [i].name));
      }
   }

   return names;
}

void Shared_memory::put_alias (const string &name, const string &alias) const
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      for (int i = 0; i < MAX_ENTRIES; i++)
      {
//         if (directory->entries [i].name [0] == '\0')
//         {
//            break;
//         }
         if (!directory->entries [i].lock)
         {
            break;
         }

         while (directory->entries [i].name [0] == '\0')
         {
            cout << "   put_alias waiting for entry name to be written..." << i << endl;
            mb();
         }

         if (strncmp(name.c_str(), reinterpret_cast<const char *>(directory->entries [i].name), MAX_NAME) == 0)
         {
            strncpy(reinterpret_cast<char *>(directory->entries [i].alias), alias.c_str (), MAX_ALIAS);
            break;
         }
      }
   }
}

string Shared_memory::get_name (const string &alias) const
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   if (directory != nullptr)
   {
//   cout << "nodes: " << directory->nodes << endl;
      for (int i = 0; i < MAX_ENTRIES; i++)
      {
//         if (directory->entries [i].name [0] == '\0')
//         {
//            break;
//         }
         if (!directory->entries [i].lock)
         {
            break;
         }

         while (directory->entries [i].alias [0] == '\0')
         {
            cout << "   get_name waiting for entry alias to be written..." << i << endl;
            mb();
         }

         if (strncmp(alias.c_str(), reinterpret_cast<const char *>(directory->entries [i].alias), MAX_ALIAS) == 0)
         {
            return reinterpret_cast<const char *>(directory->entries [i].name);
         }
      }
   }

   return "name not found";
}

void Shared_memory::barrier ()
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());
//   cout << "nodes: " << directory->nodes << endl;

   barrier_sense ^= true;

   if (__sync_sub_and_fetch (&directory->barrier_count, 1) == 0)
   {
      cout << "resetting barrier..." << endl;
         cout << "barrier: " << directory->barrier_count
              << ", " << directory->barrier_sense
              << ", " << barrier_sense << endl;
   cout << "nodes: " << directory->nodes << endl;

      directory->barrier_count = directory->nodes;
      wmb();

      directory->barrier_sense = barrier_sense;
         cout << "barrier: " << directory->barrier_count
              << ", " << directory->barrier_sense
              << ", " << barrier_sense << endl;
   cout << "nodes: " << directory->nodes << endl;
   }
   else
   {
         cout << "barrier: " << directory->barrier_count
              << ", " << directory->barrier_sense
              << ", " << barrier_sense << endl;
   cout << "nodes: " << directory->nodes << endl;
      while (barrier_sense != directory->barrier_sense)
      {
         mb();
      }
         cout << "barrier: " << directory->barrier_count
              << ", " << directory->barrier_sense
              << ", " << barrier_sense << endl;
   cout << "nodes: " << directory->nodes << endl;
   }
}

static uint8_t *create_pointer (domid_t domid, int nodes)
{
   Hypervisor *hypervisor = Hypervisor::get_instance ();

   const unsigned int size = SHARED_PAGES * PAGE_SIZE;
   uint8_t *pointer = static_cast<uint8_t *>(aligned_alloc (PAGE_SIZE, size));
   memset(static_cast<void *>(pointer), 0, size);

   for (int i = 0; i < nodes; i++)
   {
      for (int j = 0; j < SHARED_PAGES; j++)
      {
         hypervisor->grant_table.grant_access (domid + 1 + i, &pointer [j * PAGE_SIZE]);
      }
   }

   return pointer;
}

Shared_memory_creator::Shared_memory_creator (domid_t domid, int nodes)
   : pointer(create_pointer(domid, nodes))
{
   directory_t *directory = reinterpret_cast<directory_t *>(pointer);

   directory->nodes = nodes;
   directory->barrier_count = nodes;
   directory->barrier_sense = false;

   directory->next_offset = 2 * PAGE_SIZE;

//   cout << "nodes: " << directory->nodes << endl;
}

Shared_memory_creator::~Shared_memory_creator ()
{
   delete pointer;
}

uint8_t *Shared_memory_creator::get_pointer () const
{
   return pointer;
}

Shared_memory_user::Shared_memory_user (domid_t domid, int node)
   : grant_map(domid-1-node, (node * SHARED_PAGES), SHARED_PAGES)
//   : grant_map(domid-1-node, 49151 - (node * SHARED_PAGES), SHARED_PAGES)
//   : grant_map(domid-1-node, 32767 - (node * SHARED_PAGES), SHARED_PAGES)
//   : grant_map(domid-1-node, 16383 - (node * SHARED_PAGES), SHARED_PAGES)
{
   directory_t *directory = reinterpret_cast<directory_t *>(get_pointer ());

   cout << "nodes: " << directory->nodes << endl;
}

uint8_t *Shared_memory_user::get_pointer () const
{
   return reinterpret_cast<uint8_t *>(grant_map.get_pointer ());
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*-
 *
 * Quadra, an action puzzle game
 * Copyright (C) 1998-2000  Ludus Design
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "config.h"
#include "url.h"
#include "http_post.h"
#include "dict.h"
#include "stringtable.h"
#include "video.h"
#include "qserv.h"

RCSID("$Id$")

Dword Qserv::http_addr=0;
int Qserv::http_port=0;

Qserv::Qserv() {
	req=NULL;
	status[0]=0;
	reply=NULL;

	const char* host;
	int port;
	char path[256];

	Url url(config.info.game_server_address);
	if(!url.getPort())
		url.setPort(80);
	if(!strcmp(url.getHost(), ""))
		url.setHost("ludusdesign.com:80");
	if(!strcmp(url.getPath(), "/"))
		url.setPath("/cgibin/qserv.pl");

	Url proxy(config.info2.proxy_address);
	if(!proxy.getPort())
		proxy.setPort(80);

	if(strlen(proxy.getHost())) {
		//Use proxy info for host and port, and full game server address for path
		host = proxy.getHost();
		port = proxy.getPort();
		url.getFull(path);
	}
	else {
		//No proxy configuration, use game server address for everything
		host = url.getHost();
		port = url.getPort();
		strcpy(path, url.getPath());
	}

	//Use IP cache if set
	if(http_addr)
		req=new Http_post(host, http_addr, http_port, path);
	else
		req=new Http_post(host, port, path);

	req->add_data_raw("data=");
}

Qserv::~Qserv() {
	if(req)
		delete req;
	if(reply)
		delete reply;
}

bool Qserv::done() {
	if(!req)
		return true;
	if(!req->done())
		return false;

	//Save ip info for future requests
	Qserv::http_addr = req->gethostaddr();
	Qserv::http_port = req->gethostport();

	//Parse reply
	reply=new Dict();
	if(!req->getsize()) {
		strcpy(status, "");
	}
	else {
		Stringtable st(req->getbuf(), req->getsize());
		int i=0;
		for(i=0; i<st.size(); i++)
			if(strlen(st.get(i))==0) { //end of HTTP header
				i++; // Skip blank line
				if(i>=st.size())
					strcpy(status, "");
				else {
					strncpy(status, st.get(i), sizeof(status)-1);
					status[sizeof(status)-1]=0;
					i++; // Skip status line
				}
				break;
			}
		while(i<st.size()) {
			//msgbox("Qserv::done: adding [%-60.60s]\n", st.get(i));
			reply->add(st.get(i));
			i++;
		}
	}
	delete req;
	req=NULL;
	msgbox("Qserv::done: done\n");
	return true;
}

void Qserv::add_data(const char *s, ...) {
	char st[32768];
	Textbuf buf;
	va_list marker;
	va_start(marker, s);
	vsprintf(st, s, marker);
	va_end(marker);
	Http_request::url_encode(st, buf);
	req->add_data_raw(buf.get());
}

void Qserv::send() {
	req->add_data_encode("info/language %i\n", config.info.language);
	req->add_data_encode("info/registered %i\n", 1);
	req->add_data_encode("info/quadra_version %i.%i.%i\n", config.major, config.minor, config.patchlevel);
	req->add_data_encode("info/platform/os %s\n",
		#if defined(UGS_DIRECTX)
			"Windows"
		#elif defined(UGS_LINUX)
			"Linux i386"
		#else
			#error "What platform???"
		#endif
	);
	if(video_is_dumb)
		req->add_data_encode("info/platform/display None\n");
	else {
		#if defined(UGS_LINUX)
		req->add_data_encode("info/platform/display %s\n", video->xwindow ? "Xlib":"Svgalib");
		#endif
		#if defined(UGS_DIRECTX)
		req->add_data_encode("info/platform/display DirectX\n");
		#endif
	}
	req->send();
}

const char *Qserv::get_status() {
	if(status[0])
		return status;
	else
		return NULL;
}

Dict *Qserv::get_reply() {
	return reply;
}

bool Qserv::isconnected() const {
	if(req && req->isconnected())
		return true;
	return false;
}

Dword Qserv::getnbrecv() const {
	int val = 0;
	if(req) {
		val = req->getsize();
		if(val < 0)
			val = 0;
	}
	return val;
}
<commit_msg>Started changing the URL for qserv.<commit_after>/* -*- Mode: C++; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*-
 *
 * Quadra, an action puzzle game
 * Copyright (C) 1998-2000  Ludus Design
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "config.h"
#include "url.h"
#include "http_post.h"
#include "dict.h"
#include "stringtable.h"
#include "video.h"
#include "qserv.h"

RCSID("$Id$")

Dword Qserv::http_addr=0;
int Qserv::http_port=0;

Qserv::Qserv() {
	req=NULL;
	status[0]=0;
	reply=NULL;

	const char* host;
	int port;
	char path[256];

	Url url(config.info.game_server_address);
	if(!url.getPort())
		url.setPort(80);
	if(!strcmp(url.getHost(), ""))
		url.setHost("ludusdesign.com:80");
	if(!strcmp(url.getPath(), "/"))
		url.setPath("/cgi-bin/qserv.pl");

	Url proxy(config.info2.proxy_address);
	if(!proxy.getPort())
		proxy.setPort(80);

	if(strlen(proxy.getHost())) {
		//Use proxy info for host and port, and full game server address for path
		host = proxy.getHost();
		port = proxy.getPort();
		url.getFull(path);
	}
	else {
		//No proxy configuration, use game server address for everything
		host = url.getHost();
		port = url.getPort();
		strcpy(path, url.getPath());
	}

	//Use IP cache if set
	if(http_addr)
		req=new Http_post(host, http_addr, http_port, path);
	else
		req=new Http_post(host, port, path);

	req->add_data_raw("data=");
}

Qserv::~Qserv() {
	if(req)
		delete req;
	if(reply)
		delete reply;
}

bool Qserv::done() {
	if(!req)
		return true;
	if(!req->done())
		return false;

	//Save ip info for future requests
	Qserv::http_addr = req->gethostaddr();
	Qserv::http_port = req->gethostport();

	//Parse reply
	reply=new Dict();
	if(!req->getsize()) {
		strcpy(status, "");
	}
	else {
		Stringtable st(req->getbuf(), req->getsize());
		int i=0;
		for(i=0; i<st.size(); i++)
			if(strlen(st.get(i))==0) { //end of HTTP header
				i++; // Skip blank line
				if(i>=st.size())
					strcpy(status, "");
				else {
					strncpy(status, st.get(i), sizeof(status)-1);
					status[sizeof(status)-1]=0;
					i++; // Skip status line
				}
				break;
			}
		while(i<st.size()) {
			//msgbox("Qserv::done: adding [%-60.60s]\n", st.get(i));
			reply->add(st.get(i));
			i++;
		}
	}
	delete req;
	req=NULL;
	msgbox("Qserv::done: done\n");
	return true;
}

void Qserv::add_data(const char *s, ...) {
	char st[32768];
	Textbuf buf;
	va_list marker;
	va_start(marker, s);
	vsprintf(st, s, marker);
	va_end(marker);
	Http_request::url_encode(st, buf);
	req->add_data_raw(buf.get());
}

void Qserv::send() {
	req->add_data_encode("info/language %i\n", config.info.language);
	req->add_data_encode("info/registered %i\n", 1);
	req->add_data_encode("info/quadra_version %i.%i.%i\n", config.major, config.minor, config.patchlevel);
	req->add_data_encode("info/platform/os %s\n",
		#if defined(UGS_DIRECTX)
			"Windows"
		#elif defined(UGS_LINUX)
			"Linux i386"
		#else
			#error "What platform???"
		#endif
	);
	if(video_is_dumb)
		req->add_data_encode("info/platform/display None\n");
	else {
		#if defined(UGS_LINUX)
		req->add_data_encode("info/platform/display %s\n", video->xwindow ? "Xlib":"Svgalib");
		#endif
		#if defined(UGS_DIRECTX)
		req->add_data_encode("info/platform/display DirectX\n");
		#endif
	}
	req->send();
}

const char *Qserv::get_status() {
	if(status[0])
		return status;
	else
		return NULL;
}

Dict *Qserv::get_reply() {
	return reply;
}

bool Qserv::isconnected() const {
	if(req && req->isconnected())
		return true;
	return false;
}

Dword Qserv::getnbrecv() const {
	int val = 0;
	if(req) {
		val = req->getsize();
		if(val < 0)
			val = 0;
	}
	return val;
}
<|endoftext|>


<commit_before>/* BSD 3-Clause License:
 * Copyright (c) 2018, bitsofcotton.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 *    Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation or other materials provided with the distribution.
 *    Neither 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.
 */

#if !defined(_TILT_)

#include <Eigen/Core>
#include <Eigen/LU>
#include <vector>
#include <cmath>

using namespace Eigen;
using std::min;
using std::max;
using std::ceil;
using std::sqrt;
using std::cerr;
using std::endl;
using std::flush;
using std::vector;
using std::abs;
using std::isfinite;

template <typename T> class triangles_t {
public:
  Eigen::Matrix<T, 3, 3> p;
  Eigen::Matrix<T, 3, 1> n;
  T                      c;
  T                      z;
  triangles_t<T>& rotate(const Eigen::Matrix<T, 3, 3>& R, const Eigen::Matrix<T, 3, 1>& origin) {
    for(int i = 0; i < 3; i ++)
      p.col(i) = R * (p.col(i) - origin) + origin;
    return *this;
  }
  triangles_t<T>& solveN() {
    const auto pq(p.col(1) - p.col(0));
    const auto pr(p.col(2) - p.col(0));
    n[0] =   (pq[1] * pr[2] - pq[2] * pr[1]);
    n[1] = - (pq[0] * pr[2] - pq[2] * pr[0]);
    n[2] =   (pq[0] * pr[1] - pq[1] * pr[0]);
    if(n.dot(n) > 0)
      n /= sqrt(n.dot(n));
    z = n.dot(p.col(0));
    return *this;
  }
};

template <typename T> class match_t;
template <typename T> class tilter {
public:
  typedef Matrix<T, Dynamic, Dynamic> Mat;
  typedef Matrix<T, 3, 3>             Mat3x3;
  typedef Matrix<T, 3, 1>             Vec3;
  typedef Matrix<T, 2, 1>             Vec2;
  typedef triangles_t<T>              Triangles;

  tilter();
  ~tilter();
  void initialize(const T& z_ratio);

  Mat  tilt(const Mat& in, const Mat& bump, const int& idx, const int& samples, const T& psi);
  Mat  tilt(const Mat& in, const Mat& bump, const match_t<T>& m);
  Mat  tilt(const Mat& in, const vector<Triangles>& triangles0, const match_t<T>& m);
  Mat  tilt(const Mat& in, const vector<Triangles>& triangles);
  Triangles makeTriangle(const int& u, const int& v, const Mat& in, const Mat& bump, const int& flg);
  bool sameSide2(const Vec2& p0, const Vec2& p1, const Vec2& p, const Vec2& q, const bool& extend = true, const T& err = T(1e-5));
  bool sameSide2(const Vec3& p0, const Vec3& p1, const Vec3& p, const Vec3& q, const bool& extend = true, const T& err = T(1e-5));

private:
  T    sgn(const T& x);
  bool onTriangle(T& z, const Triangles& tri, const Vec2& geom);
  T    Pi;
  T    z_ratio;
};

template <typename T> tilter<T>::tilter() {
  initialize(1.);
  return;
}

template <typename T> tilter<T>::~tilter() {
  ;
}

template <typename T> void tilter<T>::initialize(const T& z_ratio) {
  this->z_ratio = z_ratio;
  Pi            = atan2(T(1), T(1)) * T(4);
  return;
}

template <typename T> T tilter<T>::sgn(const T& x) {
  if(x < T(0))
    return - T(1);
  if(x > T(0))
    return   T(1);
  return T(0);
}

template <typename T> triangles_t<T> tilter<T>::makeTriangle(const int& u, const int& v, const Mat& in, const Mat& bump, const int& flg) {
  Triangles work;
  if(flg) {
    work.p(0, 0) = u;
    work.p(1, 0) = v;
    work.p(0, 1) = u + 1;
    work.p(1, 1) = v;
    work.p(0, 2) = u + 1;
    work.p(1, 2) = v + 1;
  } else {
    work.p(0, 0) = u;
    work.p(1, 0) = v;
    work.p(0, 1) = u;
    work.p(1, 1) = v + 1;
    work.p(0, 2) = u + 1;
    work.p(1, 2) = v + 1;
  }
  work.c = T(0);
  for(int i = 0; i < 3;  i ++) {
    work.p(2, i) = bump(int(work.p(0, i)), int(work.p(1, i))) * z_ratio;
    work.c      += in(int(work.p(0, i)), int(work.p(1, i)));
  }
  work.c /= T(3);
  return work.solveN();
}

template <typename T> bool tilter<T>::sameSide2(const Vec2& p0, const Vec2& p1, const Vec2& p2, const Vec2& q, const bool& extend, const T& err) {
  const Vec2 dlt(p1 - p0);
  Vec2 dp(p2 - p0);
  dp -= dlt.dot(dp) * dlt / dlt.dot(dlt);
  // N.B. dp.dot(p1 - p0) >> 0.
  return dp.dot(q - p0) >= (extend ? - T(1) : T(1)) * (abs(dp[0]) + abs(dp[1])) * err;
}

template <typename T> bool tilter<T>::sameSide2(const Vec3& p0, const Vec3& p1, const Vec3& p2, const Vec3& q, const bool& extend, const T& err) {
  return sameSide2(Vec2(p0[0], p0[1]), Vec2(p1[0], p1[1]),
                   Vec2(p2[0], p2[1]), Vec2(q[0],  q[1]),
                   extend, err);
}

// <[x, y, t], triangle.n> == triangle.z
template <typename T> bool tilter<T>::onTriangle(T& z, const Triangles& tri, const Vec2& geom) {
  Vec3 v0;
  Vec3 camera;
  v0[0] = 0;
  v0[1] = 0;
  v0[2] = 1;
  camera[0] = geom[0];
  camera[1] = geom[1];
  camera[2] = 0;
  // <v0 t + camera, tri.n> = tri.z
  const T t((tri.z - tri.n.dot(camera)) / (tri.n.dot(v0)));
  z = camera[2] + v0[2] * t;
  return (sameSide2(tri.p.col(0), tri.p.col(1), tri.p.col(2), camera, true, T(.125)) &&
          sameSide2(tri.p.col(1), tri.p.col(2), tri.p.col(0), camera, true, T(.125)) &&
          sameSide2(tri.p.col(2), tri.p.col(0), tri.p.col(1), camera, true, T(.125)));
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> tilter<T>::tilt(const Mat& in, const Mat& bump, const int& idx, const int& samples, const T& psi) {
  const T theta(2. * Pi * idx / samples);
  const T lpsi(Pi * psi);
  Mat3x3 R0;
  Mat3x3 R1;
  R0(0, 0) =   cos(theta);
  R0(0, 1) = - sin(theta);
  R0(0, 2) = 0.;
  R0(1, 0) =   sin(theta);
  R0(1, 1) =   cos(theta);
  R0(1, 2) = 0.;
  R0(2, 0) = 0.;
  R0(2, 1) = 0.;
  R0(2, 2) = 1.;
  R1(0, 0) = 1.;
  R1(0, 1) = 0.;
  R1(0, 2) = 0.;
  R1(1, 0) = 0.;
  R1(1, 1) =   cos(lpsi);
  R1(1, 2) = - sin(lpsi);
  R1(2, 0) = 0.;
  R1(2, 1) =   sin(lpsi);
  R1(2, 2) =   cos(lpsi);
  Vec3 pcenter;
  pcenter[0] = T(in.rows() - 1.) / 2;
  pcenter[1] = T(in.cols() - 1.) / 2;
  pcenter[2] = T(.5);
  match_t<T> m;
  m.rot    = R0.transpose() * R1 * R0;
  m.offset = pcenter - m.rot * pcenter;
  m.ratio  = T(1);
  return tilt(in, bump, m);
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> tilter<T>::tilt(const Mat& in, const Mat& bump, const match_t<T>& m) {
  assert(in.rows() == bump.rows() && in.cols() == bump.cols());
  vector<Triangles> triangles;
  triangles.reserve((in.rows() - 1) * (in.cols() - 1) * 2);
  for(int i = 0; i < in.rows() - 1; i ++)
    for(int j = 0; j < in.cols() - 1; j ++) {
      triangles.push_back(makeTriangle(i, j, in, bump, false));
      triangles.push_back(makeTriangle(i, j, in, bump, true));
    }
  return tilt(in, triangles, m);
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> tilter<T>::tilt(const Mat& in, const vector<Triangles>& triangles0, const match_t<T>& m) {
  vector<Triangles> triangles(triangles0);
  for(int j = 0; j < triangles.size(); j ++) {
    for(int k = 0; k < 3; k ++)
      triangles[j].p.col(k) = m.transform(triangles[j].p.col(k));
    triangles[j].solveN();
  }
  return tilt(in, triangles);
}

template <typename T> Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> tilter<T>::tilt(const Mat& in, const vector<Triangles>& triangles) {
  Mat result(in.rows(), in.cols());
  for(int i = 0; i < in.rows(); i ++)
    for(int j = 0; j < in.cols(); j ++)
      result(i, j) = 0.;
  cerr << "t" << flush;
  Mat zb(in.rows(), in.cols());
  for(int j = 0; j < zb.rows(); j ++)
    for(int k = 0; k < zb.cols(); k ++)
      zb(j, k) = - T(1e8);
  // able to boost with divide and conquer.
#if defined(_OPENMP)
#pragma omp parallel for schedule(static, 1)
#endif
  for(int j = 0; j < triangles.size(); j ++) {
    const Triangles& tri(triangles[j]);
    int ll = int( min(min(tri.p(0, 0), tri.p(0, 1)), tri.p(0, 2)));
    int rr = ceil(max(max(tri.p(0, 0), tri.p(0, 1)), tri.p(0, 2))) + 1;
    int bb = int( min(min(tri.p(1, 0), tri.p(1, 1)), tri.p(1, 2)));
    int tt = ceil(max(max(tri.p(1, 0), tri.p(1, 1)), tri.p(1, 2))) + 1;
    for(int y = max(0, ll); y < min(rr, int(in.rows())); y ++)
      for(int x = max(0, bb); x < min(tt, int(in.cols())); x ++) {
        T z;
        Vec2 midgeom;
        midgeom[0] = y;
        midgeom[1] = x;
#if defined(_OPENMP)
#pragma omp critical
#endif
        {
          if(onTriangle(z, tri, midgeom) && isfinite(z) && zb(y, x) < z) {
            result(y, x) = tri.c;
            zb(y, x)     = z;
          }
        }
      }
  }
  return result;
}

#define _TILT_
#endif

<commit_msg>Delete tilt.hh<commit_after><|endoftext|>