<commit_before>/* <src/capi.cpp>
 *
 * This file is part of the x0 web server project and is released under GPL-3.
 * http://www.xzero.io/
 *
 * (c) 2009-2013 Christian Parpart <trapni@gmail.com>
 */

#include <x0/capi.h>
#include <x0/http/HttpServer.h>
#include <x0/http/HttpWorker.h>
#include <x0/http/HttpRequest.h>
#include <x0/io/BufferSource.h>
#include <cstdarg>

using namespace x0;

struct x0_server_s
{
	HttpServer server;

	x0_server_s(struct ev_loop* loop) :
		server(loop)
	{}
};

struct x0_request_s
{
	x0_server_t* server;
	HttpRequest* request;

	x0_request_body_fn body_cb;
	void* body_userdata;

	void bodyCallback(const BufferRef& ref) {
		if (body_cb) {
			body_cb(this, ref.data(), ref.size(), body_userdata);
		}
	}
};

x0_server_t* x0_server_create(struct ev_loop* loop)
{
	auto s = new x0_server_t(loop);

	s->server.requestHandler = [](HttpRequest* r) -> bool {
		BufferSource body("Hello, I am lazy to serve anything; I wasn't configured properly\n");

		r->status = HttpStatus::InternalServerError;

		char buf[40];
		snprintf(buf, sizeof(buf), "%zu", body.size());
		r->responseHeaders.push_back("Content-Length", buf);

		r->responseHeaders.push_back("Content-Type", "plain/text");
		r->write<BufferSource>(body);

		r->finish();

		return true;
	};

	return s;
}

int x0_listener_add(x0_server_t* server, const char* bind, int port, int backlog)
{
	auto listener = server->server.setupListener(bind, port, 128);
	if (listener == nullptr)
		return -1;

	return 0;
}

void x0_server_destroy(x0_server_t* server, int kill)
{
	if (!kill) {
		// TODO wait until all current connections have been finished, if more than one worker has been set up
	}
	delete server;
}

void x0_server_stop(x0_server_t* server)
{
	server->server.stop();
}

void x0_setup_handler(x0_server_t* server, x0_request_handler_fn handler, void* userdata)
{
	server->server.requestHandler = [=](HttpRequest* r) -> bool {
		auto rr = new x0_request_t;
		rr->request = r;
		rr->server = server;
		handler(rr, userdata);
		return true;
	};
}

void x0_request_body_callback(x0_request_t* r, x0_request_body_fn handler, void* userdata)
{
	r->request->setBodyCallback<x0_request_t, &x0_request_t::bodyCallback>(r);
}

void x0_setup_connection_limit(x0_server_t* li, size_t limit)
{
	li->server.maxConnections = limit;
}

void x0_setup_timeouts(x0_server_t* server, int read, int write)
{
	server->server.maxReadIdle = TimeSpan::fromSeconds(read);
	server->server.maxWriteIdle = TimeSpan::fromSeconds(write);
}

void x0_setup_keepalive(x0_server_t* server, int count, int timeout)
{
	server->server.maxKeepAliveRequests = count;
	server->server.maxKeepAlive = TimeSpan::fromSeconds(timeout);
}

// --------------------------------------------------------------------------
// REQUEST

int x0_request_method(x0_request_t* r)
{
	if (r->request->method == "GET")
		return X0_REQUEST_METHOD_GET;

	if (r->request->method == "POST")
		return X0_REQUEST_METHOD_POST;

	if (r->request->method == "PUT")
		return X0_REQUEST_METHOD_PUT;

	if (r->request->method == "DELETE")
		return X0_REQUEST_METHOD_DELETE;

	return X0_REQUEST_METHOD_UNKNOWN;
}

size_t x0_request_method_str(x0_request_t* r, char* buf, size_t size)
{
	if (!size)
		return 0;

	size_t n = std::min(r->request->method.size(), size - 1);
	memcpy(buf, r->request->method.data(), n);
	buf[n] = '\0';
	return n;
}

size_t x0_request_path(x0_request_t* r, char* buf, size_t size)
{
	size_t rsize = std::min(size - 1, r->request->path.size());
	memcpy(buf, r->request->path.data(), rsize);
	buf[rsize] = '\0';
	return rsize + 1;
}

int x0_request_version(x0_request_t* r)
{
	static const struct {
		int major;
		int minor;
		int code;
	} versions[] = {
		{ 0, 9, X0_HTTP_VERSION_0_9 },
		{ 1, 0, X0_HTTP_VERSION_1_0 },
		{ 1, 1, X0_HTTP_VERSION_1_1 },
		{ 2, 0, X0_HTTP_VERSION_2_0 },
	};

	int major = r->request->httpVersionMajor;
	int minor = r->request->httpVersionMinor;

	for (const auto& version: versions)
		if (version.major == major && version.minor == minor)
			return version.code;

	return X0_HTTP_VERSION_UNKNOWN;
}

int x0_request_header_exists(x0_request_t* r, const char* name)
{
	for (const auto& header: r->request->requestHeaders)
		if (header.name == name)
			return 1;

	return 0;
}

int x0_request_header_get(x0_request_t* r, const char* name, char* buf, size_t size)
{
	if (size) {
		for (const auto& header: r->request->requestHeaders) {
			if (header.name == name) {
				size_t len = std::min(header.value.size(), size - 1);
				memcpy(buf, header.value.data(), len);
				buf[len] = '\0';
				return len;
			}
		}
	}

	return 0;
}

int x0_request_cookie_get(x0_request_t* r, const char* cookie, char* buf, size_t size)
{
	return 0; // TODO cookie retrieval
}

int x0_request_header_count(x0_request_t* r)
{
	return r->request->requestHeaders.size();
}

int x0_request_header_geti(x0_request_t* r, off_t index, char* buf, size_t size)
{
	if (size && index < r->request->requestHeaders.size()) {
		const auto& header = r->request->requestHeaders[index];
		size_t len = std::min(header.value.size(), size - 1);
		memcpy(buf, header.value.data(), len);
		buf[len] = '\0';
		return len;
	}
	return 0;
}

// --------------------------------------------------------------------------
// RESPONSE

void x0_response_status_set(x0_request_t* r, int code)
{
	r->request->status = static_cast<HttpStatus>(code);
}

void x0_response_header_set(x0_request_t* r, const char* name, const char* value)
{
	r->request->responseHeaders.overwrite(name, value);
}

void x0_response_write(x0_request_t* r, const char* buf, size_t size)
{
	Buffer b;
	b.push_back(buf, size);
	r->request->write<BufferSource>(b);
}

void x0_response_printf(x0_request_t* r, const char* fmt, ...)
{
	Buffer b;
	va_list ap;

	va_start(ap, fmt);
	b.vprintf(fmt, ap);
	va_end(ap);

	r->request->write<BufferSource>(b);
}

void x0_response_vprintf(x0_request_t* r, const char* fmt, va_list args)
{
	Buffer b;
	va_list va;

	va_copy(va, args);
	b.vprintf(fmt, va);
	va_end(va);

	r->request->write<BufferSource>(b);
}

void x0_response_finish(x0_request_t* r)
{
	r->request->finish();
	delete r;
}

void x0_response_sendfile(x0_request_t* r, const char* path)
{
	r->request->sendfile(path);
}
<commit_msg>capi: fixes<commit_after>/* <src/capi.cpp>
 *
 * This file is part of the x0 web server project and is released under GPL-3.
 * http://www.xzero.io/
 *
 * (c) 2009-2013 Christian Parpart <trapni@gmail.com>
 */

#include <x0/capi.h>
#include <x0/http/HttpServer.h>
#include <x0/http/HttpWorker.h>
#include <x0/http/HttpRequest.h>
#include <x0/io/BufferSource.h>
#include <cstdarg>

using namespace x0;

struct x0_server_s
{
	HttpServer server;

	x0_server_s(struct ev_loop* loop) :
		server(loop)
	{}
};

struct x0_request_s
{
	x0_server_t* server;
	HttpRequest* request;

	x0_request_body_fn body_cb;
	void* body_userdata;

	x0_request_s(HttpRequest* r, x0_server_t* s) :
		server(s),
		request(r),
		body_cb(nullptr),
		body_userdata(nullptr)
	{
	}

	void bodyCallback(const BufferRef& ref) {
		if (body_cb) {
			body_cb(this, ref.data(), ref.size(), body_userdata);
		}
	}
};

x0_server_t* x0_server_create(struct ev_loop* loop)
{
	auto s = new x0_server_t(loop);

	s->server.requestHandler = [](HttpRequest* r) -> bool {
		BufferSource body("Hello, I am lazy to serve anything; I wasn't configured properly\n");

		r->status = HttpStatus::InternalServerError;

		char buf[40];
		snprintf(buf, sizeof(buf), "%zu", body.size());
		r->responseHeaders.push_back("Content-Length", buf);

		r->responseHeaders.push_back("Content-Type", "plain/text");
		r->write<BufferSource>(body);

		r->finish();

		return true;
	};

	return s;
}

int x0_listener_add(x0_server_t* server, const char* bind, int port, int backlog)
{
	auto listener = server->server.setupListener(bind, port, 128);
	if (listener == nullptr)
		return -1;

	return 0;
}

void x0_server_destroy(x0_server_t* server, int kill)
{
	if (!kill) {
		// TODO wait until all current connections have been finished, if more than one worker has been set up
	}
	delete server;
}

void x0_server_stop(x0_server_t* server)
{
	server->server.stop();
}

void x0_setup_handler(x0_server_t* server, x0_request_handler_fn handler, void* userdata)
{
	server->server.requestHandler = [=](HttpRequest* r) -> bool {
		auto rr = new x0_request_t(r, server);
		handler(rr, userdata);
		return true;
	};
}

void x0_request_body_callback(x0_request_t* r, x0_request_body_fn handler, void* userdata)
{
	r->request->setBodyCallback<x0_request_t, &x0_request_t::bodyCallback>(r);
}

void x0_setup_connection_limit(x0_server_t* li, size_t limit)
{
	li->server.maxConnections = limit;
}

void x0_setup_timeouts(x0_server_t* server, int read, int write)
{
	server->server.maxReadIdle = TimeSpan::fromSeconds(read);
	server->server.maxWriteIdle = TimeSpan::fromSeconds(write);
}

void x0_setup_keepalive(x0_server_t* server, int count, int timeout)
{
	server->server.maxKeepAliveRequests = count;
	server->server.maxKeepAlive = TimeSpan::fromSeconds(timeout);
}

// --------------------------------------------------------------------------
// REQUEST

int x0_request_method(x0_request_t* r)
{
	if (r->request->method == "GET")
		return X0_REQUEST_METHOD_GET;

	if (r->request->method == "POST")
		return X0_REQUEST_METHOD_POST;

	if (r->request->method == "PUT")
		return X0_REQUEST_METHOD_PUT;

	if (r->request->method == "DELETE")
		return X0_REQUEST_METHOD_DELETE;

	return X0_REQUEST_METHOD_UNKNOWN;
}

size_t x0_request_method_str(x0_request_t* r, char* buf, size_t size)
{
	if (!size)
		return 0;

	size_t n = std::min(r->request->method.size(), size - 1);
	memcpy(buf, r->request->method.data(), n);
	buf[n] = '\0';
	return n;
}

size_t x0_request_path(x0_request_t* r, char* buf, size_t size)
{
	size_t rsize = std::min(size - 1, r->request->path.size());
	memcpy(buf, r->request->path.data(), rsize);
	buf[rsize] = '\0';
	return rsize + 1;
}

int x0_request_version(x0_request_t* r)
{
	static const struct {
		int major;
		int minor;
		int code;
	} versions[] = {
		{ 0, 9, X0_HTTP_VERSION_0_9 },
		{ 1, 0, X0_HTTP_VERSION_1_0 },
		{ 1, 1, X0_HTTP_VERSION_1_1 },
		{ 2, 0, X0_HTTP_VERSION_2_0 },
	};

	int major = r->request->httpVersionMajor;
	int minor = r->request->httpVersionMinor;

	for (const auto& version: versions)
		if (version.major == major && version.minor == minor)
			return version.code;

	return X0_HTTP_VERSION_UNKNOWN;
}

int x0_request_header_exists(x0_request_t* r, const char* name)
{
	for (const auto& header: r->request->requestHeaders)
		if (header.name == name)
			return 1;

	return 0;
}

int x0_request_header_get(x0_request_t* r, const char* name, char* buf, size_t size)
{
	if (size) {
		for (const auto& header: r->request->requestHeaders) {
			if (header.name == name) {
				size_t len = std::min(header.value.size(), size - 1);
				memcpy(buf, header.value.data(), len);
				buf[len] = '\0';
				return len;
			}
		}
	}

	return 0;
}

int x0_request_cookie_get(x0_request_t* r, const char* cookie, char* buf, size_t size)
{
	return 0; // TODO cookie retrieval
}

int x0_request_header_count(x0_request_t* r)
{
	return r->request->requestHeaders.size();
}

int x0_request_header_geti(x0_request_t* r, off_t index, char* buf, size_t size)
{
	if (size && index < r->request->requestHeaders.size()) {
		const auto& header = r->request->requestHeaders[index];
		size_t len = std::min(header.value.size(), size - 1);
		memcpy(buf, header.value.data(), len);
		buf[len] = '\0';
		return len;
	}
	return 0;
}

// --------------------------------------------------------------------------
// RESPONSE

void x0_response_status_set(x0_request_t* r, int code)
{
	r->request->status = static_cast<HttpStatus>(code);
}

void x0_response_header_set(x0_request_t* r, const char* name, const char* value)
{
	r->request->responseHeaders.overwrite(name, value);
}

void x0_response_write(x0_request_t* r, const char* buf, size_t size)
{
	Buffer b;
	b.push_back(buf, size);
	r->request->write<BufferSource>(b);
}

void x0_response_printf(x0_request_t* r, const char* fmt, ...)
{
	Buffer b;
	va_list ap;

	va_start(ap, fmt);
	b.vprintf(fmt, ap);
	va_end(ap);

	r->request->write<BufferSource>(b);
}

void x0_response_vprintf(x0_request_t* r, const char* fmt, va_list args)
{
	Buffer b;
	va_list va;

	va_copy(va, args);
	b.vprintf(fmt, va);
	va_end(va);

	r->request->write<BufferSource>(b);
}

void x0_response_finish(x0_request_t* r)
{
	r->request->finish();
	delete r;
}

void x0_response_sendfile(x0_request_t* r, const char* path)
{
	r->request->sendfile(path);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Christian Lockley
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

#include "watchdogd.hpp"

#include "sub.hpp"
#include "main.hpp"
#include "init.hpp"
#include "configfile.hpp"
#include "threads.hpp"
#include "identify.hpp"
#include "bootstatus.hpp"
#include "multicall.hpp"
extern "C" {
#include "dbusapi.h"
}
#include <systemd/sd-event.h>
const bool DISARM_WATCHDOG_BEFORE_REBOOT = true;
static volatile sig_atomic_t quit = 0;

volatile sig_atomic_t stop = 0;
volatile sig_atomic_t stopPing = 0;
ProcessList processes;

static void PrintConfiguration(struct cfgoptions *const cfg)
{
	Logmsg(LOG_INFO,
	       "int=%is realtime=%s sync=%s softboot=%s force=%s mla=%.2f mem=%li pid=%li",
	       cfg->sleeptime, cfg->options & REALTIME ? "yes" : "no",
	       cfg->options & SYNC ? "yes" : "no",
	       cfg->options & SOFTBOOT ? "yes" : "no",
	       cfg->options & FORCE ? "yes" : "no", cfg->maxLoadOne, cfg->minfreepages, getppid());

	if (cfg->options & ENABLEPING) {
		for (int cnt = 0; cnt < config_setting_length(cfg->ipAddresses); cnt++) {
			const char *ipAddress = config_setting_get_string_elem(cfg->ipAddresses,
									       cnt);

			assert(ipAddress != NULL);

			Logmsg(LOG_INFO, "ping: %s", ipAddress);
		}
	} else {
		Logmsg(LOG_INFO, "ping: no ip adresses to ping");
	}

	if (cfg->options & ENABLEPIDCHECKER) {
		for (int cnt = 0; cnt < config_setting_length(cfg->pidFiles); cnt++) {
			const char *pidFilePathName = config_setting_get_string_elem(cfg->pidFiles, cnt);

			assert(pidFilePathName != NULL);

			Logmsg(LOG_DEBUG, "pidfile: %s", pidFilePathName);
		}
	} else {
		Logmsg(LOG_INFO, "pidfile: no server process to check");
	}

	Logmsg(LOG_INFO, "test=%s(%i) repair=%s(%i) no_act=%s",
	       cfg->testexepathname == NULL ? "no" : cfg->testexepathname,
	       cfg->testBinTimeout,
	       cfg->exepathname == NULL ? "no" : cfg->exepathname,
	       cfg->repairBinTimeout, cfg->options & NOACTION ? "yes" : "no");
}

static void BlockSignals()
{
	sigset_t set;

	sigemptyset(&set);

	sigaddset(&set, SIGTERM);
	sigaddset(&set, SIGUSR2);
	sigaddset(&set, SIGINT);
	sigaddset(&set, SIGHUP);

	pthread_sigmask(SIG_BLOCK, &set, NULL);
}

static int SignalHandler(sd_event_source * s, const signalfd_siginfo * si, void *cxt)
{
	switch (sd_event_source_get_signal(s)) {
	case SIGTERM:
	case SIGINT:
		quit = 1;
		sd_event_exit((sd_event *) cxt, 0);
		break;
	case SIGHUP:
		//reload;
		break;
	}
	return 1;
}

static void InstallSignalHandlers(sd_event * event)
{
	int r1 = sd_event_add_signal(event, NULL, SIGTERM, SignalHandler, event);
	int r2 = sd_event_add_signal(event, NULL, SIGHUP, SignalHandler, event);
	int r3 = sd_event_add_signal(event, NULL, SIGUSR2, SignalHandler, event);
	int r4 = sd_event_add_signal(event, NULL, SIGINT, SignalHandler, event);

	if (r1 < 0 || r2 < 0 || r3 < 0 || r4 < 0) {
		abort();
	}
}

static int Pinger(sd_event_source * s, uint64_t usec, void *cxt)
{
	Watchdog *watchdog = (Watchdog *) cxt;
	watchdog->Ping();

	sd_event_now(sd_event_source_get_event(s), CLOCK_REALTIME, &usec);
	usec += watchdog->GetPingInterval() * 1000000;
	sd_event_add_time(sd_event_source_get_event(s), &s, CLOCK_REALTIME, usec, 1, Pinger, (void *)cxt);
	return 0;
}

static bool InstallPinger(sd_event * e, int time, Watchdog * w)
{
	sd_event_source *s = NULL;
	uint64_t usec = 0;
	w->SetPingInterval(time);

	sd_event_now(e, CLOCK_REALTIME, &usec);

	sd_event_add_time(e, &s, CLOCK_REALTIME, usec, 1, Pinger, (void *)w);
	return true;
}

int ServiceMain(int argc, char **argv, int fd, bool restarted)
{
	cfgoptions options;
	Watchdog watchdog;
	cfgoptions *tmp = &options;
	Watchdog *tmp2 = &watchdog;

	struct dbusinfo temp = {.config = &tmp,.wdt = &tmp2 };;
	temp.fd = fd;

	if (MyStrerrorInit() == false) {
		std::perror("Unable to create a new locale object");
		return EXIT_FAILURE;
	}

	int ret = ParseCommandLine(&argc, argv, &options);

	if (ret < 0) {
		return EXIT_FAILURE;
	} else if (ret != 0) {
		return EXIT_SUCCESS;
	}

	if (strcasecmp(GetExeName(), "wd_identify") == 0 || strcasecmp(GetExeName(), "wd_identify.sh") == 0) {
		options.options |= IDENTIFY;
	}

	if (ReadConfigurationFile(&options) < 0) {
		return EXIT_FAILURE;
	}

	if (options.options & IDENTIFY) {
		watchdog.Open(options.devicepath);

		ret = Identify(watchdog.GetRawTimeout(), (const char *)watchdog.GetIdentity(),
			       options.devicepath, options.options & VERBOSE);

		watchdog.Close();
		return ret;
	}

	if (PingInit(&options) < 0) {
		return EXIT_FAILURE;
	}

	if (restarted) {
		Logmsg(LOG_INFO,"restarting service (%s)", PACKAGE_VERSION);
	} else {
		Logmsg(LOG_INFO, "starting service (%s)", PACKAGE_VERSION);
	}

	PrintConfiguration(&options);

	if (ExecuteRepairScriptsPreFork(&processes, &options) == false) {
		Logmsg(LOG_ERR, "ExecuteRepairScriptsPreFork failed");
		FatalError(&options);
	}

	sd_event *event = NULL;
	sd_event_default(&event);

	BlockSignals();
	InstallSignalHandlers(event);

	if (StartHelperThreads(&options) != 0) {
		FatalError(&options);
	}

	pthread_t dbusThread;

	if (!(options.options & NOACTION)) {
		errno = 0;

		ret = watchdog.Open(options.devicepath);

		if (errno == EBUSY && ret < 0) {
			Logmsg(LOG_ERR, "Unable to open watchdog device");
			return EXIT_FAILURE;
		} else if (ret <= -1) {
			LoadKernelModule();
			ret = watchdog.Open(options.devicepath);
		}

		if (ret <= -1) {
			FatalError(&options);
		}

		if (watchdog.ConfigureWatchdogTimeout(options.watchdogTimeout)
		    < 0 && options.watchdogTimeout != -1) {
			Logmsg(LOG_ERR, "unable to set watchdog device timeout\n");
			Logmsg(LOG_ERR, "program exiting\n");
			EndDaemon(&options, false);
			watchdog.Close();
			return EXIT_FAILURE;
		}

		if (options.sleeptime == -1) {
			options.sleeptime = watchdog.GetOptimalPingInterval();
			Logmsg(LOG_INFO, "ping interval autodetect: %i", options.sleeptime);
		}

		if (options.watchdogTimeout != -1 && watchdog.CheckWatchdogTimeout(options.sleeptime) == true) {
			Logmsg(LOG_ERR, "WDT timeout is less than or equal watchdog daemon ping interval");
			Logmsg(LOG_ERR, "Using this interval may result in spurious reboots");

			if (!(options.options & FORCE)) {
				watchdog.Close();
				Logmsg(LOG_WARNING, "use the -f option to force this configuration");
				return EXIT_FAILURE;
			}
		}

		WriteBootStatus(watchdog.GetStatus(), "/run/watchdogd.status", options.sleeptime,
				watchdog.GetRawTimeout());

		static struct identinfo i;

		strncpy(i.name, (char *)watchdog.GetIdentity(), sizeof(i.name) - 1);
		i.timeout = watchdog.GetRawTimeout();
		strncpy(i.daemonVersion, PACKAGE_VERSION, sizeof(i.daemonVersion) - 1);
		strncpy(i.deviceName, options.devicepath, sizeof(i.deviceName) - 1);
		i.flags = watchdog.GetStatus();
		i.firmwareVersion = watchdog.GetFirmwareVersion();

		CreateDetachedThread(IdentityThread, &i);
		pthread_create(&dbusThread, NULL, DbusHelper, &temp);
		InstallPinger(event, options.sleeptime, &watchdog);

		write(fd, "", sizeof(char));
	}

	if (SetupAuxManagerThread(&options) < 0) {
		FatalError(&options);
	}

	if (PlatformInit() != true) {
		FatalError(&options);
	}

	sd_event_loop(event);

	if (stop == 1) {
		while (true) {
			if (stopPing == 1) {
				if (DISARM_WATCHDOG_BEFORE_REBOOT) {
					watchdog.Close();
				}
			} else {
				watchdog.Ping();
			}

			sleep(1);
		}
	}

	if (!(options.options & NOACTION)) {
		pthread_cancel(dbusThread);
		pthread_join(dbusThread, NULL);
	}

	watchdog.Close();

	unlink("/run/watchdogd.status");

	if (EndDaemon(&options, false) < 0) {
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}

int main(int argc, char **argv)
{
	int sock[2] = { 0 };
	socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sock);
	pid_t pid = fork();

	if (pid == 0) {
		OnParentDeathSend(SIGKILL);
		close(sock[1]);
		DbusApiInit(sock[0]);
		_Exit(0);
	}
	close(sock[0]);

	sigset_t mask;
	bool restarted = false;
	char name[64] = {0};
	sd_bus *bus = NULL;
	sd_bus_message *m = NULL;
	sd_bus_error error = {0};
	int fildes[2] = {0};
	sigemptyset(&mask);
	sigaddset(&mask, SIGTERM);
	sigaddset(&mask, SIGINT);
	sigaddset(&mask, SIGHUP);
	sigaddset(&mask, SIGCHLD);
	sigprocmask(SIG_BLOCK, &mask, NULL);
	int sfd = signalfd (-1, &mask, 0);
init:
	pipe(fildes);
	pid = fork();

	if (pid == 0) {
		close(sfd);
		ResetSignalHandlers(64);
		sigprocmask(SIG_UNBLOCK, &mask, NULL);
		close(fildes[1]);
		read(fildes[0], fildes+1, sizeof(int));
		close(fildes[0]);

		_Exit(ServiceMain(argc, argv, sock[1], restarted));
	} else {
		sd_bus_open_system(&bus);

		sprintf(name, "watchdogd.%li.scope", pid);
		sd_bus_message_new_method_call(bus, &m, "org.freedesktop.systemd1",
					"/org/freedesktop/systemd1",
					"org.freedesktop.systemd1.Manager",
					"StartTransientUnit");
		sd_bus_message_append(m, "ss", name, "fail");
		sd_bus_message_open_container(m, 'a', "(sv)");
		sd_bus_message_append(m, "(sv)", "Description", "s", " ");
		sd_bus_message_append(m, "(sv)", "KillSignal", "i", SIGKILL);
		sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) pid);
		sd_bus_message_close_container(m);
		sd_bus_message_append(m, "a(sa(sv))", 0);
		sd_bus_message * reply;
		sd_bus_call(bus, m, 0, &error, &reply);

		close(fildes[0]);
		close(fildes[1]);

		sd_bus_flush_close_unref(bus);
	}

	sd_notifyf(0, "READY=1\n" "MAINPID=%lu", (unsigned long)getpid());
	while (true) {
		struct signalfd_siginfo si = {0};
		ssize_t ret = read (sfd, &si, sizeof(si));
		switch (si.ssi_signo) {
		case SIGHUP:
			sd_bus_open_system(&bus);
			sd_bus_call_method(bus, "org.freedesktop.systemd1",
					"/org/freedesktop/systemd1",
					"org.freedesktop.systemd1.Manager", "StopUnit", &error,
					NULL, "ss", name, "ignore-dependencies");
			sd_bus_flush_close_unref(bus);
			restarted = true;
			si.ssi_signo = 0;
			goto init;
			break;
		case SIGINT:
		case SIGTERM:
		case SIGCHLD:
			sd_bus_open_system(&bus);
			sd_bus_call_method(bus, "org.freedesktop.systemd1",
					"/org/freedesktop/systemd1",
					"org.freedesktop.systemd1.Manager", "StopUnit", &error,
					NULL, "ss", name, "ignore-dependencies");
			sd_bus_flush_close_unref(bus);
			_Exit(si.ssi_status);
			break;
		}
	}
}
<commit_msg>cleanup<commit_after>/*
 * Copyright 2016 Christian Lockley
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

#include "watchdogd.hpp"

#include "sub.hpp"
#include "main.hpp"
#include "init.hpp"
#include "configfile.hpp"
#include "threads.hpp"
#include "identify.hpp"
#include "bootstatus.hpp"
#include "multicall.hpp"
extern "C" {
#include "dbusapi.h"
}
#include <systemd/sd-event.h>
const bool DISARM_WATCHDOG_BEFORE_REBOOT = true;
static volatile sig_atomic_t quit = 0;

volatile sig_atomic_t stop = 0;
volatile sig_atomic_t stopPing = 0;
ProcessList processes;

static void PrintConfiguration(struct cfgoptions *const cfg)
{
	Logmsg(LOG_INFO,
	       "int=%is realtime=%s sync=%s softboot=%s force=%s mla=%.2f mem=%li pid=%li",
	       cfg->sleeptime, cfg->options & REALTIME ? "yes" : "no",
	       cfg->options & SYNC ? "yes" : "no",
	       cfg->options & SOFTBOOT ? "yes" : "no",
	       cfg->options & FORCE ? "yes" : "no", cfg->maxLoadOne, cfg->minfreepages, getppid());

	if (cfg->options & ENABLEPING) {
		for (int cnt = 0; cnt < config_setting_length(cfg->ipAddresses); cnt++) {
			const char *ipAddress = config_setting_get_string_elem(cfg->ipAddresses,
									       cnt);

			assert(ipAddress != NULL);

			Logmsg(LOG_INFO, "ping: %s", ipAddress);
		}
	} else {
		Logmsg(LOG_INFO, "ping: no ip adresses to ping");
	}

	if (cfg->options & ENABLEPIDCHECKER) {
		for (int cnt = 0; cnt < config_setting_length(cfg->pidFiles); cnt++) {
			const char *pidFilePathName = config_setting_get_string_elem(cfg->pidFiles, cnt);

			assert(pidFilePathName != NULL);

			Logmsg(LOG_DEBUG, "pidfile: %s", pidFilePathName);
		}
	} else {
		Logmsg(LOG_INFO, "pidfile: no server process to check");
	}

	Logmsg(LOG_INFO, "test=%s(%i) repair=%s(%i) no_act=%s",
	       cfg->testexepathname == NULL ? "no" : cfg->testexepathname,
	       cfg->testBinTimeout,
	       cfg->exepathname == NULL ? "no" : cfg->exepathname,
	       cfg->repairBinTimeout, cfg->options & NOACTION ? "yes" : "no");
}

static void BlockSignals()
{
	sigset_t set;

	sigemptyset(&set);

	sigaddset(&set, SIGTERM);
	sigaddset(&set, SIGUSR2);
	sigaddset(&set, SIGINT);
	sigaddset(&set, SIGHUP);

	pthread_sigmask(SIG_BLOCK, &set, NULL);
}

static int SignalHandler(sd_event_source * s, const signalfd_siginfo * si, void *cxt)
{
	switch (sd_event_source_get_signal(s)) {
	case SIGTERM:
	case SIGINT:
		quit = 1;
		sd_event_exit((sd_event *) cxt, 0);
		break;
	case SIGHUP:
		//reload;
		break;
	}
	return 1;
}

static void InstallSignalHandlers(sd_event * event)
{
	int r1 = sd_event_add_signal(event, NULL, SIGTERM, SignalHandler, event);
	int r2 = sd_event_add_signal(event, NULL, SIGHUP, SignalHandler, event);
	int r3 = sd_event_add_signal(event, NULL, SIGUSR2, SignalHandler, event);
	int r4 = sd_event_add_signal(event, NULL, SIGINT, SignalHandler, event);

	if (r1 < 0 || r2 < 0 || r3 < 0 || r4 < 0) {
		abort();
	}
}

static int Pinger(sd_event_source * s, uint64_t usec, void *cxt)
{
	Watchdog *watchdog = (Watchdog *) cxt;
	watchdog->Ping();

	sd_event_now(sd_event_source_get_event(s), CLOCK_REALTIME, &usec);
	usec += watchdog->GetPingInterval() * 1000000;
	sd_event_add_time(sd_event_source_get_event(s), &s, CLOCK_REALTIME, usec, 1, Pinger, (void *)cxt);
	return 0;
}

static bool InstallPinger(sd_event * e, int time, Watchdog * w)
{
	sd_event_source *s = NULL;
	uint64_t usec = 0;
	w->SetPingInterval(time);

	sd_event_now(e, CLOCK_REALTIME, &usec);

	sd_event_add_time(e, &s, CLOCK_REALTIME, usec, 1, Pinger, (void *)w);
	return true;
}

int ServiceMain(int argc, char **argv, int fd, bool restarted)
{
	cfgoptions options;
	Watchdog watchdog;
	cfgoptions *tmp = &options;
	Watchdog *tmp2 = &watchdog;

	struct dbusinfo temp = {.config = &tmp,.wdt = &tmp2 };;
	temp.fd = fd;

	if (MyStrerrorInit() == false) {
		std::perror("Unable to create a new locale object");
		return EXIT_FAILURE;
	}

	int ret = ParseCommandLine(&argc, argv, &options);

	if (ret < 0) {
		return EXIT_FAILURE;
	} else if (ret != 0) {
		return EXIT_SUCCESS;
	}

	if (strcasecmp(GetExeName(), "wd_identify") == 0 || strcasecmp(GetExeName(), "wd_identify.sh") == 0) {
		options.options |= IDENTIFY;
	}

	if (ReadConfigurationFile(&options) < 0) {
		return EXIT_FAILURE;
	}

	if (options.options & IDENTIFY) {
		watchdog.Open(options.devicepath);

		ret = Identify(watchdog.GetRawTimeout(), (const char *)watchdog.GetIdentity(),
			       options.devicepath, options.options & VERBOSE);

		watchdog.Close();
		return ret;
	}

	if (PingInit(&options) < 0) {
		return EXIT_FAILURE;
	}

	if (restarted) {
		Logmsg(LOG_INFO,"restarting service (%s)", PACKAGE_VERSION);
	} else {
		Logmsg(LOG_INFO, "starting service (%s)", PACKAGE_VERSION);
	}

	PrintConfiguration(&options);

	if (ExecuteRepairScriptsPreFork(&processes, &options) == false) {
		Logmsg(LOG_ERR, "ExecuteRepairScriptsPreFork failed");
		FatalError(&options);
	}

	sd_event *event = NULL;
	sd_event_default(&event);

	BlockSignals();
	InstallSignalHandlers(event);

	if (StartHelperThreads(&options) != 0) {
		FatalError(&options);
	}

	pthread_t dbusThread;

	if (!(options.options & NOACTION)) {
		errno = 0;

		ret = watchdog.Open(options.devicepath);

		if (errno == EBUSY && ret < 0) {
			Logmsg(LOG_ERR, "Unable to open watchdog device");
			return EXIT_FAILURE;
		} else if (ret <= -1) {
			LoadKernelModule();
			ret = watchdog.Open(options.devicepath);
		}

		if (ret <= -1) {
			FatalError(&options);
		}

		if (watchdog.ConfigureWatchdogTimeout(options.watchdogTimeout)
		    < 0 && options.watchdogTimeout != -1) {
			Logmsg(LOG_ERR, "unable to set watchdog device timeout\n");
			Logmsg(LOG_ERR, "program exiting\n");
			EndDaemon(&options, false);
			watchdog.Close();
			return EXIT_FAILURE;
		}

		if (options.sleeptime == -1) {
			options.sleeptime = watchdog.GetOptimalPingInterval();
			Logmsg(LOG_INFO, "ping interval autodetect: %i", options.sleeptime);
		}

		if (options.watchdogTimeout != -1 && watchdog.CheckWatchdogTimeout(options.sleeptime) == true) {
			Logmsg(LOG_ERR, "WDT timeout is less than or equal watchdog daemon ping interval");
			Logmsg(LOG_ERR, "Using this interval may result in spurious reboots");

			if (!(options.options & FORCE)) {
				watchdog.Close();
				Logmsg(LOG_WARNING, "use the -f option to force this configuration");
				return EXIT_FAILURE;
			}
		}

		WriteBootStatus(watchdog.GetStatus(), "/run/watchdogd.status", options.sleeptime,
				watchdog.GetRawTimeout());

		static struct identinfo i;

		strncpy(i.name, (char *)watchdog.GetIdentity(), sizeof(i.name) - 1);
		i.timeout = watchdog.GetRawTimeout();
		strncpy(i.daemonVersion, PACKAGE_VERSION, sizeof(i.daemonVersion) - 1);
		strncpy(i.deviceName, options.devicepath, sizeof(i.deviceName) - 1);
		i.flags = watchdog.GetStatus();
		i.firmwareVersion = watchdog.GetFirmwareVersion();

		CreateDetachedThread(IdentityThread, &i);
		pthread_create(&dbusThread, NULL, DbusHelper, &temp);
		InstallPinger(event, options.sleeptime, &watchdog);

		write(fd, "", sizeof(char));
	}

	if (SetupAuxManagerThread(&options) < 0) {
		FatalError(&options);
	}

	if (PlatformInit() != true) {
		FatalError(&options);
	}

	sd_event_loop(event);

	if (stop == 1) {
		while (true) {
			if (stopPing == 1) {
				if (DISARM_WATCHDOG_BEFORE_REBOOT) {
					watchdog.Close();
				}
			} else {
				watchdog.Ping();
			}

			sleep(1);
		}
	}

	if (!(options.options & NOACTION)) {
		pthread_cancel(dbusThread);
		pthread_join(dbusThread, NULL);
	}

	watchdog.Close();

	unlink("/run/watchdogd.status");

	if (EndDaemon(&options, false) < 0) {
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}

int main(int argc, char **argv)
{
	int sock[2] = { 0 };
	socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sock);
	pid_t pid = fork();

	if (pid == 0) {
		OnParentDeathSend(SIGKILL);
		close(sock[1]);
		DbusApiInit(sock[0]);
		_Exit(0);
	}
	close(sock[0]);

	sigset_t mask;
	bool restarted = false;
	char name[64] = {0};
	sd_bus *bus = NULL;
	sd_bus_message *m = NULL;
	sd_bus_error error = {0};
	int fildes[2] = {0};
	sigemptyset(&mask);
	sigaddset(&mask, SIGTERM);
	sigaddset(&mask, SIGINT);
	sigaddset(&mask, SIGHUP);
	sigaddset(&mask, SIGCHLD);
	sigprocmask(SIG_BLOCK, &mask, NULL);
	int sfd = signalfd (-1, &mask, SFD_CLOEXEC);
init:
	waitpid(-1, NULL, WNOHANG);

	pipe(fildes);
	pid = fork();

	if (pid == 0) {
		close(sfd);
		ResetSignalHandlers(64);
		sigfillset(&mask);
		sigprocmask(SIG_UNBLOCK, &mask, NULL);
		close(fildes[1]);
		read(fildes[0], fildes+1, sizeof(int));
		close(fildes[0]);

		_Exit(ServiceMain(argc, argv, sock[1], restarted));
	}

	sd_bus_open_system(&bus);
	sprintf(name, "watchdogd.%li.scope", pid);
	sd_bus_message_new_method_call(bus, &m, "org.freedesktop.systemd1",
				"/org/freedesktop/systemd1",
				"org.freedesktop.systemd1.Manager",
				"StartTransientUnit");
	sd_bus_message_append(m, "ss", name, "fail");
	sd_bus_message_open_container(m, 'a', "(sv)");
	sd_bus_message_append(m, "(sv)", "Description", "s", " ");
	sd_bus_message_append(m, "(sv)", "KillSignal", "i", SIGKILL);
	sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) pid);
	sd_bus_message_close_container(m);
	sd_bus_message_append(m, "a(sa(sv))", 0);
	sd_bus_message * reply;
	sd_bus_call(bus, m, 0, &error, &reply);
	sd_bus_flush_close_unref(bus);

	close(fildes[0]);
	close(fildes[1]);

	sd_notifyf(0, "READY=1\n" "MAINPID=%lu", (unsigned long)getpid());

	while (true) {
		struct signalfd_siginfo si = {0};
		ssize_t ret = read (sfd, &si, sizeof(si));
		switch (si.ssi_signo) {
		case SIGHUP:
			sd_bus_open_system(&bus);
			sd_bus_call_method(bus, "org.freedesktop.systemd1",
					"/org/freedesktop/systemd1",
					"org.freedesktop.systemd1.Manager", "StopUnit", &error,
					NULL, "ss", name, "ignore-dependencies");
			sd_bus_flush_close_unref(bus);
			restarted = true;
			si.ssi_signo = 0;
			goto init;
			break;
		case SIGINT:
		case SIGTERM:
		case SIGCHLD:
			sd_bus_open_system(&bus);
			sd_bus_call_method(bus, "org.freedesktop.systemd1",
					"/org/freedesktop/systemd1",
					"org.freedesktop.systemd1.Manager", "StopUnit", &error,
					NULL, "ss", name, "ignore-dependencies");
			sd_bus_flush_close_unref(bus);
			_Exit(si.ssi_status);
			break;
		}
	}
}
<|endoftext|>


<commit_before>/* Copyright 2014 Andrew Schwartzmeyer
 *
 * Source file for derived genetic algorithm class
 */

#include <algorithm>
#include <iostream>
#include <iterator>

#include "genetic_algorithm.hpp"
#include "random_generator.hpp"

const Individual Genetic::mutate(const Individual & subject) const {
  // unit Gaussian distribution for delta
  Individual mutant = subject;
  int_dist percent(1, 100);
  normal_dist delta_dist(mean, stddev);
  for (parameter & gene : mutant)
    if (problem.chance || percent(rg.engine) < int(100 * problem.chance))
      mutant.mutate(gene, gene * delta_dist(rg.engine));
  // update fitness
  mutant.fitness = problem.fitness(mutant);
  return mutant;
}

const Individual Genetic::selection(const Genetic::population & contestants) const {
  // return best Individual from a set of contestants
  return *std::max_element(contestants.begin(), contestants.end());
}

const Genetic::population Genetic::crossover(const Genetic::population & mates) const {
  // return two offspring for two mates
  return mates;
}

const Individual Genetic::solve() const {
  while(true) {
    // create initial population
    population generation;
    for (int i = 0; i < population_size; ++i)
      generation.emplace_back(problem.potential());
    // generations loop
    for (long i = 0; i < problem.iterations; ++i) {
      // find generation's best member (general form of selection)
      const Individual best = selection(generation);
      // terminating condition
      if (best.fitness > problem.goal) return best;
      // std::cout << best.fitness << '\n';
      // selection and mutation stage
      population offspring;
      while(offspring.size() != population_size) {
	// tournament selection of parents
	population parents;
	for (int i = 0; i < crossover_size; ++i) {
	  population contestants;
	  int_dist population_dist(0, population_size-1); // closed interval
	  // create tournament of random members drawn from generation
	  for (int i = 0; i < tournament_size; ++i)
	    contestants.emplace_back(generation[population_dist(rg.engine)]);
	  // select best member from each tournament
	  parents.emplace_back(selection(contestants));
	}
	// crossover
	population children = crossover(parents);
	// add mutated children to offspring
	for (const Individual child : children) offspring.emplace_back(mutate(child));
      }
      // replace generation with offspring
      generation.swap(offspring);
    }
    std::cout << "Exhausted generations!\n";
  }
}
<commit_msg>Implementing arithmetic corssover<commit_after>/* Copyright 2014 Andrew Schwartzmeyer
 *
 * Source file for derived genetic algorithm class
 */

#include <algorithm>
#include <iostream>
#include <iterator>

#include "genetic_algorithm.hpp"
#include "random_generator.hpp"

const Individual Genetic::mutate(const Individual & subject) const {
  // unit Gaussian distribution for delta
  Individual mutant = subject;
  int_dist percent(1, 100);
  normal_dist delta_dist(mean, stddev);
  for (parameter & gene : mutant)
    if (problem.chance || percent(rg.engine) < int(100 * problem.chance))
      mutant.mutate(gene, gene * delta_dist(rg.engine));
  // update fitness
  mutant.fitness = problem.fitness(mutant);
  return mutant;
}

const Individual Genetic::selection(const Genetic::population & contestants) const {
  // return best Individual from a set of contestants
  return *std::max_element(contestants.begin(), contestants.end());
}

const Genetic::population Genetic::crossover(const Genetic::population & parents) const {
  population children = parents;
  // arithmetic binary crossover
  if (crossover_size == 2) {
    real_dist alpha_dist(-0.1, 1.1);
    parameter alpha = alpha_dist(rg.engine);
    for (unsigned long i = 0; i < parents[0].size(); ++i) {
      children[0][i] = alpha * parents[0][i] + (1 - alpha) * parents[1][i];
      children[1][i] = (1 - alpha) * parents[0][i] + alpha * parents[1][i];
    }
  }
  else {
    // implement uniform crossover
  }
  // update fitnesses
  for (Individual & child : children) child.fitness = problem.fitness(child);
  return children;
}

const Individual Genetic::solve() const {
  while(true) {
    // create initial population
    population generation;
    for (int i = 0; i < population_size; ++i)
      generation.emplace_back(problem.potential());
    // generations loop
    for (long i = 0; i < problem.iterations; ++i) {
      // find generation's best member (general form of selection)
      const Individual best = selection(generation);
      // terminating condition
      if (best.fitness > problem.goal) return best;
      // std::cout << best.fitness << '\n';
      // selection and mutation stage
      population offspring;
      while(offspring.size() != population_size) {
	// tournament selection of parents
	population parents;
	for (int i = 0; i < crossover_size; ++i) {
	  population contestants;
	  int_dist population_dist(0, population_size-1); // closed interval
	  // create tournament of random members drawn from generation
	  for (int i = 0; i < tournament_size; ++i)
	    contestants.emplace_back(generation[population_dist(rg.engine)]);
	  // select best member from each tournament
	  parents.emplace_back(selection(contestants));
	}
	// crossover
	population children = crossover(parents);
	// add mutated children to offspring
	for (const Individual child : children) offspring.emplace_back(mutate(child));
      }
      // replace generation with offspring
      generation.swap(offspring);
    }
    std::cout << "Exhausted generations!\n";
  }
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "shaderGen/GLSL/shaderCompGLSL.h"

#include "shaderGen/shaderComp.h"
#include "shaderGen/langElement.h"
#include "gfx/gfxDevice.h"

Var * AppVertConnectorGLSL::getElement(   RegisterType type,
                                          U32 numElements,
                                          U32 numRegisters )
{
   switch( type )
   {
      case RT_POSITION:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vPosition" );
         return newVar;
      }

      case RT_NORMAL:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vNormal" );
         return newVar;
      }

      case RT_BINORMAL:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vBinormal" );
         return newVar;
      }

      case RT_COLOR:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vColor" );
         return newVar;
      }

      case RT_TANGENT:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vTangent" );
         return newVar;
      }

      case RT_TANGENTW:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vTangentW" );
         return newVar;
      }

      case RT_TEXCOORD:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );

         char out[32];
         dSprintf( (char*)out, sizeof(out), "vTexCoord%d", mCurTexElem );
         newVar->setConnectName( out );
         newVar->constNum = mCurTexElem;
         newVar->arraySize = numElements;

         if ( numRegisters != -1 )
            mCurTexElem += numRegisters;
         else
            mCurTexElem += numElements;

         return newVar;
      }

      default:
         break;
   }

   return NULL;
}

void AppVertConnectorGLSL::sortVars()
{
   // Not required in GLSL
}

void AppVertConnectorGLSL::setName( char *newName )
{
   dStrcpy( (char*)mName, newName );
}

void AppVertConnectorGLSL::reset()
{
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      mElementList[i] = NULL;
   }

   mElementList.setSize( 0 );
   mCurTexElem = 0;
}

void AppVertConnectorGLSL::print( Stream &stream, bool isVertexShader )
{
   if(!isVertexShader)
      return;

   U8 output[256];

   // print struct
   dSprintf( (char*)output, sizeof(output), "struct VertexData\r\n" );
   stream.write( dStrlen((char*)output), output );
   dSprintf( (char*)output, sizeof(output), "{\r\n" );
   stream.write( dStrlen((char*)output), output );

   for( U32 i=0; i<mElementList.size(); i++ )
   {
      Var *var = mElementList[i];

      if( var->arraySize == 1)
      {
         dSprintf( (char*)output, sizeof(output), "   %s %s;\r\n", var->type, (char*)var->name );
         stream.write( dStrlen((char*)output), output );
      }
      else
      {
         dSprintf( (char*)output, sizeof(output), "   %s %s[%d];\r\n", var->type, (char*)var->name, var->arraySize );
         stream.write( dStrlen((char*)output), output );
      }
   }

   dSprintf( (char*)output, sizeof(output), "} IN;\r\n\r\n" );
   stream.write( dStrlen((char*)output), output );

   // print in elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      Var *var = mElementList[i];

      for(int j = 0; j < var->arraySize; ++j)
      {
         const char *name = j == 0 ? var->connectName : avar("vTexCoord%d", var->constNum + j) ;
         dSprintf( (char*)output, sizeof(output), "in %s %s;\r\n", var->type, name );
         stream.write( dStrlen((char*)output), output );
      }

      dSprintf( (char*)output, sizeof(output), "#define IN_%s IN.%s\r\n", var->name, var->name ); // TODO REMOVE
      stream.write( dStrlen((char*)output), output );
   }
   const char* newLine ="\r\n";
   stream.write( dStrlen((char*)newLine), newLine );
}

Var * VertPixelConnectorGLSL::getElement( RegisterType type,
                                          U32 numElements,
                                          U32 numRegisters )
{
   switch( type )
   {
   case RT_POSITION:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "POSITION" );
         return newVar;
      }

   case RT_NORMAL:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "NORMAL" );
         return newVar;
      }

   case RT_COLOR:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "COLOR" );
         return newVar;
      }

   /*case RT_BINORMAL:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "BINORMAL" );
         return newVar;
      }

   case RT_TANGENT:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "TANGENT" );
         return newVar;
      }   */

   case RT_TEXCOORD:
   case RT_BINORMAL:
   case RT_TANGENT:
      {
         Var *newVar = new Var;
         newVar->arraySize = numElements;

         char out[32];
         dSprintf( (char*)out, sizeof(out), "TEXCOORD%d", mCurTexElem );
         newVar->setConnectName( out );

         if ( numRegisters != -1 )
            mCurTexElem += numRegisters;
         else
            mCurTexElem += numElements;

         mElementList.push_back( newVar );
         return newVar;
      }

   default:
      break;
   }

   return NULL;
}

void VertPixelConnectorGLSL::sortVars()
{
   // Not needed in GLSL
}

void VertPixelConnectorGLSL::setName( char *newName )
{
   dStrcpy( (char*)mName, newName );
}

void VertPixelConnectorGLSL::reset()
{
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      mElementList[i] = NULL;
   }

   mElementList.setSize( 0 );
   mCurTexElem = 0;
}

void VertPixelConnectorGLSL::print( Stream &stream, bool isVerterShader )
{
   // print out elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      U8 output[256];

      Var *var = mElementList[i];
      if(!dStrcmp((const char*)var->name, "gl_Position"))
         continue;

      if(var->arraySize <= 1)
         dSprintf((char*)output, sizeof(output), "%s %s _%s_;\r\n", (isVerterShader ? "out" : "in"), var->type, var->connectName);
      else
         dSprintf((char*)output, sizeof(output), "%s %s _%s_[%d];\r\n", (isVerterShader ? "out" : "in"),var->type, var->connectName, var->arraySize);

      stream.write( dStrlen((char*)output), output );
   }

   printStructDefines(stream, !isVerterShader);
}

void VertPixelConnectorGLSL::printOnMain( Stream &stream, bool isVerterShader )
{
   if(isVerterShader)
      return;

   const char *newLine = "\r\n";
   const char *header = "   //-------------------------\r\n";
   stream.write( dStrlen((char*)newLine), newLine );
   stream.write( dStrlen((char*)header), header );

   // print out elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      U8 output[256];

      Var *var = mElementList[i];
      if(!dStrcmp((const char*)var->name, "gl_Position"))
         continue;

      dSprintf((char*)output, sizeof(output), "   %s IN_%s = _%s_;\r\n", var->type, var->name, var->connectName);

      stream.write( dStrlen((char*)output), output );
   }

   stream.write( dStrlen((char*)header), header );
   stream.write( dStrlen((char*)newLine), newLine );
}

void AppVertConnectorGLSL::printOnMain( Stream &stream, bool isVerterShader )
{
   if(!isVerterShader)
      return;

   const char *newLine = "\r\n";
   const char *header = "   //-------------------------\r\n";
   stream.write( dStrlen((char*)newLine), newLine );
   stream.write( dStrlen((char*)header), header );

   // print out elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      Var *var = mElementList[i];
      U8 output[256];

      if(var->arraySize <= 1)
      {
         dSprintf((char*)output, sizeof(output), "   IN.%s = %s;\r\n", var->name, var->connectName);
         stream.write( dStrlen((char*)output), output );
      }
      else
      {
         for(int j = 0; j < var->arraySize; ++j)
         {
            const char *name = j == 0 ? var->connectName : avar("vTexCoord%d", var->constNum + j) ;
            dSprintf((char*)output, sizeof(output), "   IN.%s[%d] = %s;\r\n", var->name, j, name );
            stream.write( dStrlen((char*)output), output );
         }
      }
   }

   stream.write( dStrlen((char*)header), header );
   stream.write( dStrlen((char*)newLine), newLine );
}

Vector<String> initDeprecadedDefines()
{
   Vector<String> vec;
   vec.push_back( "isBack");
   return vec;
}

void VertPixelConnectorGLSL::printStructDefines( Stream &stream, bool in )
{
   const char* connectionDir;

   if(in)
   {
      connectionDir = "IN";
   }
   else
   {

      connectionDir = "OUT";
   }

   static Vector<String> deprecatedDefines = initDeprecadedDefines();

   const char *newLine = "\r\n";
   const char *header = "// Struct defines\r\n";
   stream.write( dStrlen((char*)newLine), newLine );
   stream.write( dStrlen((char*)header), header );

   // print out elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      U8 output[256];

      Var *var = mElementList[i];
      if(!dStrcmp((const char*)var->name, "gl_Position"))
         continue;

      if(!in)
      {
         dSprintf((char*)output, sizeof(output), "#define %s_%s _%s_\r\n", connectionDir, var->name, var->connectName);
         stream.write( dStrlen((char*)output), output );
         continue;
      }

      if( deprecatedDefines.contains((char*)var->name))
         continue;

      dSprintf((char*)output, sizeof(output), "#define %s %s_%s\r\n", var->name, connectionDir, var->name);
      stream.write( dStrlen((char*)output), output );
   }

   stream.write( dStrlen((char*)newLine), newLine );
}

void VertexParamsDefGLSL::print( Stream &stream, bool isVerterShader )
{
   // find all the uniform variables and print them out
   for( U32 i=0; i<LangElement::elementList.size(); i++)
   {
      Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
      if( var )
      {
         if( var->uniform )
         {
            U8 output[256];
            if(var->arraySize <= 1)
               dSprintf((char*)output, sizeof(output), "uniform %-8s %-15s;\r\n", var->type, var->name);
            else
               dSprintf((char*)output, sizeof(output), "uniform %-8s %-15s[%d];\r\n", var->type, var->name, var->arraySize);

            stream.write( dStrlen((char*)output), output );
         }
      }
   }

   const char *closer = "\r\n\r\nvoid main()\r\n{\r\n";
   stream.write( dStrlen(closer), closer );
}

void PixelParamsDefGLSL::print( Stream &stream, bool isVerterShader )
{
   // find all the uniform variables and print them out
   for( U32 i=0; i<LangElement::elementList.size(); i++)
   {
      Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
      if( var )
      {
         if( var->uniform )
         {
            U8 output[256];
            if(var->arraySize <= 1)
               dSprintf((char*)output, sizeof(output), "uniform %-8s %-15s;\r\n", var->type, var->name);
            else
               dSprintf((char*)output, sizeof(output), "uniform %-8s %-15s[%d];\r\n", var->type, var->name, var->arraySize);

            stream.write( dStrlen((char*)output), output );
         }
      }
   }

   const char *closer = "\r\nvoid main()\r\n{\r\n";
   stream.write( dStrlen(closer), closer );

   for( U32 i=0; i<LangElement::elementList.size(); i++)
   {
      Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
      if( var )
      {
         if( var->uniform && !var->sampler)
         {
            U8 output[256];
            if(var->arraySize <= 1)
               dSprintf((char*)output, sizeof(output), "   %s %s = %s;\r\n", var->type, var->name, var->name);
            else
               dSprintf((char*)output, sizeof(output), "   %s %s[%d] = %s;\r\n", var->type, var->name, var->arraySize, var->name);

            stream.write( dStrlen((char*)output), output );
         }
      }
   }
}
<commit_msg>Remove some dead code from OpenGL shadergen.<commit_after>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "shaderGen/GLSL/shaderCompGLSL.h"

#include "shaderGen/shaderComp.h"
#include "shaderGen/langElement.h"
#include "gfx/gfxDevice.h"

Var * AppVertConnectorGLSL::getElement(   RegisterType type,
                                          U32 numElements,
                                          U32 numRegisters )
{
   switch( type )
   {
      case RT_POSITION:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vPosition" );
         return newVar;
      }

      case RT_NORMAL:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vNormal" );
         return newVar;
      }

      case RT_BINORMAL:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vBinormal" );
         return newVar;
      }

      case RT_COLOR:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vColor" );
         return newVar;
      }

      case RT_TANGENT:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vTangent" );
         return newVar;
      }

      case RT_TANGENTW:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "vTangentW" );
         return newVar;
      }

      case RT_TEXCOORD:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );

         char out[32];
         dSprintf( (char*)out, sizeof(out), "vTexCoord%d", mCurTexElem );
         newVar->setConnectName( out );
         newVar->constNum = mCurTexElem;
         newVar->arraySize = numElements;

         if ( numRegisters != -1 )
            mCurTexElem += numRegisters;
         else
            mCurTexElem += numElements;

         return newVar;
      }

      default:
         break;
   }

   return NULL;
}

void AppVertConnectorGLSL::sortVars()
{
   // Not required in GLSL
}

void AppVertConnectorGLSL::setName( char *newName )
{
   dStrcpy( (char*)mName, newName );
}

void AppVertConnectorGLSL::reset()
{
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      mElementList[i] = NULL;
   }

   mElementList.setSize( 0 );
   mCurTexElem = 0;
}

void AppVertConnectorGLSL::print( Stream &stream, bool isVertexShader )
{
   if(!isVertexShader)
      return;

   U8 output[256];

   // print struct
   dSprintf( (char*)output, sizeof(output), "struct VertexData\r\n" );
   stream.write( dStrlen((char*)output), output );
   dSprintf( (char*)output, sizeof(output), "{\r\n" );
   stream.write( dStrlen((char*)output), output );

   for( U32 i=0; i<mElementList.size(); i++ )
   {
      Var *var = mElementList[i];

      if( var->arraySize == 1)
      {
         dSprintf( (char*)output, sizeof(output), "   %s %s;\r\n", var->type, (char*)var->name );
         stream.write( dStrlen((char*)output), output );
      }
      else
      {
         dSprintf( (char*)output, sizeof(output), "   %s %s[%d];\r\n", var->type, (char*)var->name, var->arraySize );
         stream.write( dStrlen((char*)output), output );
      }
   }

   dSprintf( (char*)output, sizeof(output), "} IN;\r\n\r\n" );
   stream.write( dStrlen((char*)output), output );

   // print in elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      Var *var = mElementList[i];

      for(int j = 0; j < var->arraySize; ++j)
      {
         const char *name = j == 0 ? var->connectName : avar("vTexCoord%d", var->constNum + j) ;
         dSprintf( (char*)output, sizeof(output), "in %s %s;\r\n", var->type, name );
         stream.write( dStrlen((char*)output), output );
      }

      dSprintf( (char*)output, sizeof(output), "#define IN_%s IN.%s\r\n", var->name, var->name ); // TODO REMOVE
      stream.write( dStrlen((char*)output), output );
   }
   const char* newLine ="\r\n";
   stream.write( dStrlen((char*)newLine), newLine );
}

Var * VertPixelConnectorGLSL::getElement( RegisterType type,
                                          U32 numElements,
                                          U32 numRegisters )
{
   switch( type )
   {
   case RT_POSITION:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "POSITION" );
         return newVar;
      }

   case RT_NORMAL:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "NORMAL" );
         return newVar;
      }

   case RT_COLOR:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "COLOR" );
         return newVar;
      }

   /*case RT_BINORMAL:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "BINORMAL" );
         return newVar;
      }

   case RT_TANGENT:
      {
         Var *newVar = new Var;
         mElementList.push_back( newVar );
         newVar->setConnectName( "TANGENT" );
         return newVar;
      }   */

   case RT_TEXCOORD:
   case RT_BINORMAL:
   case RT_TANGENT:
      {
         Var *newVar = new Var;
         newVar->arraySize = numElements;

         char out[32];
         dSprintf( (char*)out, sizeof(out), "TEXCOORD%d", mCurTexElem );
         newVar->setConnectName( out );

         if ( numRegisters != -1 )
            mCurTexElem += numRegisters;
         else
            mCurTexElem += numElements;

         mElementList.push_back( newVar );
         return newVar;
      }

   default:
      break;
   }

   return NULL;
}

void VertPixelConnectorGLSL::sortVars()
{
   // Not needed in GLSL
}

void VertPixelConnectorGLSL::setName( char *newName )
{
   dStrcpy( (char*)mName, newName );
}

void VertPixelConnectorGLSL::reset()
{
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      mElementList[i] = NULL;
   }

   mElementList.setSize( 0 );
   mCurTexElem = 0;
}

void VertPixelConnectorGLSL::print( Stream &stream, bool isVerterShader )
{
   // print out elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      U8 output[256];

      Var *var = mElementList[i];
      if(!dStrcmp((const char*)var->name, "gl_Position"))
         continue;

      if(var->arraySize <= 1)
         dSprintf((char*)output, sizeof(output), "%s %s _%s_;\r\n", (isVerterShader ? "out" : "in"), var->type, var->connectName);
      else
         dSprintf((char*)output, sizeof(output), "%s %s _%s_[%d];\r\n", (isVerterShader ? "out" : "in"),var->type, var->connectName, var->arraySize);

      stream.write( dStrlen((char*)output), output );
   }

   printStructDefines(stream, !isVerterShader);
}

void VertPixelConnectorGLSL::printOnMain( Stream &stream, bool isVerterShader )
{
   if(isVerterShader)
      return;

   const char *newLine = "\r\n";
   const char *header = "   //-------------------------\r\n";
   stream.write( dStrlen((char*)newLine), newLine );
   stream.write( dStrlen((char*)header), header );

   // print out elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      U8 output[256];

      Var *var = mElementList[i];
      if(!dStrcmp((const char*)var->name, "gl_Position"))
         continue;

      dSprintf((char*)output, sizeof(output), "   %s IN_%s = _%s_;\r\n", var->type, var->name, var->connectName);

      stream.write( dStrlen((char*)output), output );
   }

   stream.write( dStrlen((char*)header), header );
   stream.write( dStrlen((char*)newLine), newLine );
}

void AppVertConnectorGLSL::printOnMain( Stream &stream, bool isVerterShader )
{
   if(!isVerterShader)
      return;

   const char *newLine = "\r\n";
   const char *header = "   //-------------------------\r\n";
   stream.write( dStrlen((char*)newLine), newLine );
   stream.write( dStrlen((char*)header), header );

   // print out elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      Var *var = mElementList[i];
      U8 output[256];

      if(var->arraySize <= 1)
      {
         dSprintf((char*)output, sizeof(output), "   IN.%s = %s;\r\n", var->name, var->connectName);
         stream.write( dStrlen((char*)output), output );
      }
      else
      {
         for(int j = 0; j < var->arraySize; ++j)
         {
            const char *name = j == 0 ? var->connectName : avar("vTexCoord%d", var->constNum + j) ;
            dSprintf((char*)output, sizeof(output), "   IN.%s[%d] = %s;\r\n", var->name, j, name );
            stream.write( dStrlen((char*)output), output );
         }
      }
   }

   stream.write( dStrlen((char*)header), header );
   stream.write( dStrlen((char*)newLine), newLine );
}

Vector<String> initDeprecadedDefines()
{
   Vector<String> vec;
   vec.push_back( "isBack");
   return vec;
}

void VertPixelConnectorGLSL::printStructDefines( Stream &stream, bool in )
{
   const char* connectionDir = in ? "IN" : "OUT";

   static Vector<String> deprecatedDefines = initDeprecadedDefines();

   const char *newLine = "\r\n";
   const char *header = "// Struct defines\r\n";
   stream.write( dStrlen((char*)newLine), newLine );
   stream.write( dStrlen((char*)header), header );

   // print out elements
   for( U32 i=0; i<mElementList.size(); i++ )
   {
      U8 output[256];

      Var *var = mElementList[i];
      if(!dStrcmp((const char*)var->name, "gl_Position"))
         continue;

      if(!in)
      {
         dSprintf((char*)output, sizeof(output), "#define %s_%s _%s_\r\n", connectionDir, var->name, var->connectName);
         stream.write( dStrlen((char*)output), output );
         continue;
      }
   }

   stream.write( dStrlen((char*)newLine), newLine );
}

void VertexParamsDefGLSL::print( Stream &stream, bool isVerterShader )
{
   // find all the uniform variables and print them out
   for( U32 i=0; i<LangElement::elementList.size(); i++)
   {
      Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
      if( var )
      {
         if( var->uniform )
         {
            U8 output[256];
            if(var->arraySize <= 1)
               dSprintf((char*)output, sizeof(output), "uniform %-8s %-15s;\r\n", var->type, var->name);
            else
               dSprintf((char*)output, sizeof(output), "uniform %-8s %-15s[%d];\r\n", var->type, var->name, var->arraySize);

            stream.write( dStrlen((char*)output), output );
         }
      }
   }

   const char *closer = "\r\n\r\nvoid main()\r\n{\r\n";
   stream.write( dStrlen(closer), closer );
}

void PixelParamsDefGLSL::print( Stream &stream, bool isVerterShader )
{
   // find all the uniform variables and print them out
   for( U32 i=0; i<LangElement::elementList.size(); i++)
   {
      Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
      if( var )
      {
         if( var->uniform )
         {
            U8 output[256];
            if(var->arraySize <= 1)
               dSprintf((char*)output, sizeof(output), "uniform %-8s %-15s;\r\n", var->type, var->name);
            else
               dSprintf((char*)output, sizeof(output), "uniform %-8s %-15s[%d];\r\n", var->type, var->name, var->arraySize);

            stream.write( dStrlen((char*)output), output );
         }
      }
   }

   const char *closer = "\r\nvoid main()\r\n{\r\n";
   stream.write( dStrlen(closer), closer );

   for( U32 i=0; i<LangElement::elementList.size(); i++)
   {
      Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
      if( var )
      {
         if( var->uniform && !var->sampler)
         {
            U8 output[256];
            if(var->arraySize <= 1)
               dSprintf((char*)output, sizeof(output), "   %s %s = %s;\r\n", var->type, var->name, var->name);
            else
               dSprintf((char*)output, sizeof(output), "   %s %s[%d] = %s;\r\n", var->type, var->name, var->arraySize, var->name);

            stream.write( dStrlen((char*)output), output );
         }
      }
   }
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"

#include "chainparams.h"
#include "hash.h"
#include "pow.h"
#include "uint256.h"

#include <stdint.h>

#include <boost/thread.hpp>

static const char DB_COINS = 'c';
static const char DB_BLOCK_FILES = 'f';
static const char DB_TXINDEX = 't';
static const char DB_BLOCK_INDEX = 'b';

static const char DB_BEST_BLOCK = 'B';
static const char DB_FLAG = 'F';
static const char DB_REINDEX_FLAG = 'R';
static const char DB_LAST_BLOCK = 'l';

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
{
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
    return db.Read(std::make_pair(DB_COINS, txid), coins);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) const {
    return db.Exists(std::make_pair(DB_COINS, txid));
}

uint256 CCoinsViewDB::GetBestBlock() const {
    uint256 hashBestChain;
    if (!db.Read(DB_BEST_BLOCK, hashBestChain))
        return uint256();
    return hashBestChain;
}

bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
    CDBBatch batch(db);
    size_t count = 0;
    size_t changed = 0;
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
        if (it->second.flags & CCoinsCacheEntry::DIRTY) {
            if (it->second.coins.IsPruned())
                batch.Erase(std::make_pair(DB_COINS, it->first));
            else
                batch.Write(std::make_pair(DB_COINS, it->first), it->second.coins);
            changed++;
        }
        count++;
        CCoinsMap::iterator itOld = it++;
        mapCoins.erase(itOld);
    }
    if (!hashBlock.IsNull())
        batch.Write(DB_BEST_BLOCK, hashBlock);

    LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write(DB_REINDEX_FLAG, '1');
    else
        return Erase(DB_REINDEX_FLAG);
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists(DB_REINDEX_FLAG);
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read(DB_LAST_BLOCK, nFile);
}

CCoinsViewCursor *CCoinsViewDB::Cursor() const
{
    CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast<CDBWrapper*>(&db)->NewIterator(), GetBestBlock());
    /* It seems that there are no "const iterators" for LevelDB.  Since we
       only need read operations on it, use a const-cast to get around
       that restriction.  */
    i->pcursor->Seek(DB_COINS);
    // Cache key of first record
    i->pcursor->GetKey(i->keyTmp);
    return i;
}

bool CCoinsViewDBCursor::GetKey(uint256 &key) const
{
    // Return cached key
    if (keyTmp.first == DB_COINS) {
        key = keyTmp.second;
        return true;
    }
    return false;
}

bool CCoinsViewDBCursor::GetValue(CCoins &coins) const
{
    return pcursor->GetValue(coins);
}

unsigned int CCoinsViewDBCursor::GetValueSize() const
{
    return pcursor->GetValueSize();
}

bool CCoinsViewDBCursor::Valid() const
{
    return keyTmp.first == DB_COINS;
}

void CCoinsViewDBCursor::Next()
{
    pcursor->Next();
    if (!pcursor->Valid() || !pcursor->GetKey(keyTmp))
        keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
}

bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
    CDBBatch batch(*this);
    for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
        batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second);
    }
    batch.Write(DB_LAST_BLOCK, nLastFile);
    for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
        batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
    }
    return WriteBatch(batch, true);
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(std::make_pair(DB_TXINDEX, txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CDBBatch batch(*this);
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(std::make_pair(DB_TXINDEX, it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair(DB_FLAG, name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts(boost::function<CBlockIndex*(const uint256&)> insertBlockIndex)
{
    std::unique_ptr<CDBIterator> pcursor(NewIterator());

    pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
            CDiskBlockIndex diskindex;
            if (pcursor->GetValue(diskindex)) {
                // Construct block index object
                CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = insertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;
                pindexNew->hashStateRoot  = diskindex.hashStateRoot; // qtum

                if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
                    return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());

                pcursor->Next();
            } else {
                return error("LoadBlockIndex() : failed to read value");
            }
        } else {
            break;
        }
    }

    return true;
}
<commit_msg>Update the transaction db with the block index parameters for PoS<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"

#include "chainparams.h"
#include "hash.h"
#include "pow.h"
#include "uint256.h"

#include <stdint.h>

#include <boost/thread.hpp>

static const char DB_COINS = 'c';
static const char DB_BLOCK_FILES = 'f';
static const char DB_TXINDEX = 't';
static const char DB_BLOCK_INDEX = 'b';

static const char DB_BEST_BLOCK = 'B';
static const char DB_FLAG = 'F';
static const char DB_REINDEX_FLAG = 'R';
static const char DB_LAST_BLOCK = 'l';

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
{
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
    return db.Read(std::make_pair(DB_COINS, txid), coins);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) const {
    return db.Exists(std::make_pair(DB_COINS, txid));
}

uint256 CCoinsViewDB::GetBestBlock() const {
    uint256 hashBestChain;
    if (!db.Read(DB_BEST_BLOCK, hashBestChain))
        return uint256();
    return hashBestChain;
}

bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
    CDBBatch batch(db);
    size_t count = 0;
    size_t changed = 0;
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
        if (it->second.flags & CCoinsCacheEntry::DIRTY) {
            if (it->second.coins.IsPruned())
                batch.Erase(std::make_pair(DB_COINS, it->first));
            else
                batch.Write(std::make_pair(DB_COINS, it->first), it->second.coins);
            changed++;
        }
        count++;
        CCoinsMap::iterator itOld = it++;
        mapCoins.erase(itOld);
    }
    if (!hashBlock.IsNull())
        batch.Write(DB_BEST_BLOCK, hashBlock);

    LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write(DB_REINDEX_FLAG, '1');
    else
        return Erase(DB_REINDEX_FLAG);
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists(DB_REINDEX_FLAG);
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read(DB_LAST_BLOCK, nFile);
}

CCoinsViewCursor *CCoinsViewDB::Cursor() const
{
    CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast<CDBWrapper*>(&db)->NewIterator(), GetBestBlock());
    /* It seems that there are no "const iterators" for LevelDB.  Since we
       only need read operations on it, use a const-cast to get around
       that restriction.  */
    i->pcursor->Seek(DB_COINS);
    // Cache key of first record
    i->pcursor->GetKey(i->keyTmp);
    return i;
}

bool CCoinsViewDBCursor::GetKey(uint256 &key) const
{
    // Return cached key
    if (keyTmp.first == DB_COINS) {
        key = keyTmp.second;
        return true;
    }
    return false;
}

bool CCoinsViewDBCursor::GetValue(CCoins &coins) const
{
    return pcursor->GetValue(coins);
}

unsigned int CCoinsViewDBCursor::GetValueSize() const
{
    return pcursor->GetValueSize();
}

bool CCoinsViewDBCursor::Valid() const
{
    return keyTmp.first == DB_COINS;
}

void CCoinsViewDBCursor::Next()
{
    pcursor->Next();
    if (!pcursor->Valid() || !pcursor->GetKey(keyTmp))
        keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
}

bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
    CDBBatch batch(*this);
    for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
        batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second);
    }
    batch.Write(DB_LAST_BLOCK, nLastFile);
    for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
        batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
    }
    return WriteBatch(batch, true);
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(std::make_pair(DB_TXINDEX, txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CDBBatch batch(*this);
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(std::make_pair(DB_TXINDEX, it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair(DB_FLAG, name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts(boost::function<CBlockIndex*(const uint256&)> insertBlockIndex)
{
    std::unique_ptr<CDBIterator> pcursor(NewIterator());

    pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
            CDiskBlockIndex diskindex;
            if (pcursor->GetValue(diskindex)) {
                // Construct block index object
                CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = insertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;
                pindexNew->hashStateRoot  = diskindex.hashStateRoot; // qtum
                pindexNew->fStake         = diskindex.fStake;
                pindexNew->nStakeModifier = diskindex.nStakeModifier;
                pindexNew->prevoutStake   = diskindex.prevoutStake;
                pindexNew->nStakeTime     = diskindex.nStakeTime; // qtum

                if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
                    return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());

                pcursor->Next();
            } else {
                return error("LoadBlockIndex() : failed to read value");
            }
        } else {
            break;
        }
    }

    return true;
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2015, Eric Arnebäck(arnebackeric@gmail.com)

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

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

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

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <float.h>

using std::string;
using std::cout;
using std::endl;
using std::cerr;
using std::ifstream;
using std::vector;
using std::stringstream;
using std::stof;
using std::invalid_argument;
using std::ostream;

struct Vector {

public:
    float x,y,z;

    Vector(float x_, float y_, float z_) {
	x = x_;
	y = y_;
	z = z_;
    }

    Vector() {
	x = y = z = 0;
    }

    static float Dot(const Vector& v1, const Vector& v2) {
	return
	    v1.x * v2.x +
	    v1.y * v2.y +
	    v1.z * v2.z;
    }

    friend ostream& operator<<(ostream& os, const Vector& v) {
	os << "(" << v.x << "," << v.y << "," << v.z << ")";
	return os;
    }
};

string StripFileExtension(const string& str);
void PrintHelp();

// split a string on whitespace character.
vector<string> Split(string str);

int main(int argc, char *argv[] ) {

    /*
      Parse command line arguments:
     */

    if(argc < 2) { // not enough arguments.
	PrintHelp();
	exit(1);
    }

    for (int i = 1; i < argc; i++) {

	if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0  ) {
	    PrintHelp();
	    exit(0);
	}
    }

    // last arguent is input file
    const string inputFile = string(argv[argc-1]);

    cout << "input file: " << inputFile << endl;

    ifstream file (inputFile);

    if(file.fail()) {
	cerr << "Error: " << strerror(errno) << endl;
    }

    string line;

    Vector axes[] = {
	Vector(1,0,0),
	Vector(0,1,0),
	Vector(0,0,1),
    };

    Vector vmin[3];
    Vector vmax[3];

    float minproj[3] = {FLT_MAX, FLT_MAX, FLT_MAX };
    float maxproj[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX };

    while(getline(file, line)) {

	// we are only interested in the vertices of the model.
	// all other information(such as normals) we ignore.
	if(line[0] != 'v' || line[1] != ' ')
	    continue;

	vector<string> tokens = Split(line);

	if(tokens.size() != 4) {
	    cerr << "Invalid obj-file: every vertex line must have three integers:" << endl;
	    cerr << line << endl;
	    exit(1);
	}

	Vector pt;

	try {
	    pt.x = stof(tokens[1], NULL);
	    pt.y = stof(tokens[2], NULL);
	    pt.z = stof(tokens[3], NULL);

	} catch(const invalid_argument& e) {
	    cerr << "Invalid obj-file: found vertex with invalid numbers:" << endl;
	    cerr << line << endl;
	    exit(1);
	}

	for(int iaxis = 0; iaxis < 3; ++iaxis) {

	    Vector axis = axes[iaxis];

	    float proj = Vector::Dot(pt, axis);

	    if (proj < minproj[iaxis]) {
		minproj[iaxis] = proj;

		vmin[iaxis] = pt;
	    }
	    // Keep track of most distant point along direction vector
	    if (proj > maxproj[iaxis]) {
		maxproj[iaxis] = proj;
		vmax[iaxis] = pt;

//		*imax = i;
	    }

	}

    }

    cout << "xmin " << vmin[0] << endl;
    cout << "xmax " << vmax[0] << endl;

    cout << "ymin " << vmin[1] << endl;
    cout << "ymax " << vmax[1] << endl;

    cout << "zmin " << vmin[2] << endl;
    cout << "zmax " << vmax[2] << endl;

}

string StripFileExtension(const string& str) {
    size_t last_dot = str.find_last_of(".");

    return str.substr(0,last_dot);
}

void PrintHelp() {
    printf("Usage:\n");
    printf("aabb_create [FLAGS] input-file\n\n");

//    printf("Flags:\n");
//    printf("\t-h,--help\t\tPrint this message\n");
//    printf( "\t-fs,--font-size\t\tFont size. Default value: %d\n", FONT_SIZE_DEFALT );

}

vector<string> Split(string str) {
    string buffer;
    stringstream ss(str);

    vector<string> tokens;

    while (ss >> buffer)
        tokens.push_back(buffer);

    return tokens;
}
<commit_msg>finished the program.<commit_after>/*

Copyright (c) 2015, Eric Arnebäck(arnebackeric@gmail.com)

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

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

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

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <float.h>

using std::string;
using std::cout;
using std::endl;
using std::cerr;
using std::ifstream;
using std::vector;
using std::stringstream;
using std::stof;
using std::invalid_argument;
using std::ostream;
using std::ofstream;

struct Vector {

public:
    float x,y,z;

    Vector(float x_, float y_, float z_) {
	x = x_;
	y = y_;
	z = z_;
    }

    Vector() {
	x = y = z = 0;
    }

    static float Dot(const Vector& v1, const Vector& v2) {
	return
	    v1.x * v2.x +
	    v1.y * v2.y +
	    v1.z * v2.z;
    }

    friend ostream& operator<<(ostream& os, const Vector& v) {
	os << v.x << " " << v.y << " " << v.z;
	return os;
    }
};

string StripFileExtension(const string& str);
void PrintHelp();

// split a string on whitespace character.
vector<string> Split(string str);

int main(int argc, char *argv[] ) {

    /*
      Parse command line arguments:
     */

    if(argc < 2) { // not enough arguments.
	PrintHelp();
	exit(1);
    }

    for (int i = 1; i < argc; i++) {

	if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0  ) {
	    PrintHelp();
	    exit(0);
	}
    }

    // last arguent is input file
    const string inputFile = string(argv[argc-1]);

    const string outputFile = StripFileExtension(inputFile) + ".aabb";

    ifstream file (inputFile);

    if(file.fail()) {
	cerr << "Error: " << strerror(errno) << endl;
    }

    string line;

    Vector axes[] = {
	Vector(1,0,0),
	Vector(0,1,0),
	Vector(0,0,1),
    };

    Vector vmin[3];
    Vector vmax[3];

    float minproj[3] = {FLT_MAX, FLT_MAX, FLT_MAX };
    float maxproj[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX };

    while(getline(file, line)) {

	// we are only interested in the vertices of the model.
	// all other information(such as normals) we ignore.
	if(line[0] != 'v' || line[1] != ' ')
	    continue;

	vector<string> tokens = Split(line);

	if(tokens.size() != 4) {
	    cerr << "Invalid obj-file: every vertex line must have three integers:" << endl;
	    cerr << line << endl;
	    exit(1);
	}

	Vector pt;

	try {
	    pt.x = stof(tokens[1], NULL);
	    pt.y = stof(tokens[2], NULL);
	    pt.z = stof(tokens[3], NULL);

	} catch(const invalid_argument& e) {
	    cerr << "Invalid obj-file: found vertex with invalid numbers:" << endl;
	    cerr << line << endl;
	    exit(1);
	}

	for(int iaxis = 0; iaxis < 3; ++iaxis) {

	    Vector axis = axes[iaxis];

	    float proj = Vector::Dot(pt, axis);

	    if (proj < minproj[iaxis]) {
		minproj[iaxis] = proj;

		vmin[iaxis] = pt;
	    }
	    // Keep track of most distant point along direction vector
	    if (proj > maxproj[iaxis]) {
		maxproj[iaxis] = proj;
		vmax[iaxis] = pt;
	    }

	}

    }

    /*
      Output AABB
     */

    Vector min(vmin[0].x, vmin[1].y, vmin[2].z);
    Vector max(vmax[0].x, vmax[1].y, vmax[2].z);

    ofstream outFile(outputFile);
    outFile << "max " << max << endl;
    outFile << "min " << min << endl;

    outFile.close();

}

string StripFileExtension(const string& str) {
    size_t last_dot = str.find_last_of(".");

    return str.substr(0,last_dot);
}

void PrintHelp() {
    printf("Usage:\n");
    printf("aabb_create input-file\n\n");
}

vector<string> Split(string str) {
    string buffer;
    stringstream ss(str);

    vector<string> tokens;

    while (ss >> buffer)
        tokens.push_back(buffer);

    return tokens;
}
<|endoftext|>


<commit_before>/*
*
*	TP 1 Técnicas de programación concurrentes I
*	Integrantes:
*		Bogado, Sebastián
*		Martty, Juan
*		Pereira, Fernando
*
*/

int main(int argc, char* argv[]) {

	// Init Logger (static)

	// Parse command line (--cant-surtidores --cant-empleados ¿fifo name?)

	// create jefeEstacion child process

	// create empleados child process

	return 0;
}
<commit_msg>Agrego un main dummy donde esta la utilizacion del Logger<commit_after>/*
*
*	TP 1 Técnicas de programación concurrentes I
*	Integrantes:
*		Bogado, Sebastián
*		Martty, Juan
*		Pereira, Fernando
*
*/

#include "logger/Logger.h"

const char* logFile = "/home/ferno/ferno/FIUBA/Concurrentes/TP1/log.txt";

int main(int argc, char* argv[]) {

	// Init Logger
	Logger::initialize(logFile,Logger::LOG_DEBUG);

	// Parse command line (--cant-surtidores --cant-empleados ¿--log-filename?)
	Logger::log("Se ha parseado la linea de comandos",Logger::LOG_DEBUG);

	// Fork&Exev jefeEstacion
	Logger::log("Se ha creado el hijo Jefe De Estacion",Logger::LOG_NOTICE);

	// Fork&Execv Employees
	Logger::log("Se han creado los child process",Logger::LOG_CRITICAL);

	Logger::destroy();

	return 0;
}
<|endoftext|>