<commit_before>/*****************************************************************************
 * Copyright (C) 2011-2016 Michael Ira Krufky
 *
 * Author: Michael Ira Krufky <mkrufky@linuxtv.org>
 *
 * This library 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 library 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <inttypes.h>
#include "string.h"

#include "stats.h"
#include "log.h"
#define CLASS_MODULE "stats"

#define DBG 0

#define dPrintf(fmt, arg...) __dPrintf(DBG_STATS, "(%s) " fmt, parent, ##arg)

stats::stats(const char *caller)
  : tei_count(0)
  , __timenow(0)
  , parent(caller)
  , streamtime_cb(NULL)
  , streamtime_priv(NULL)
  , statistics_cb(NULL)
  , statistics_priv(NULL)
  , statistics_iface(NULL)
{
	dPrintf("(%s)", parent);
}

stats::~stats()
{
	dPrintf("(%s)", parent);
	show(false);
}

#if 0
stats::stats(const stats&)
{
	dPrintf("(%s, copy)", parent);
}

stats& stats::operator= (const stats& cSource)
{
	dPrintf("(%s, operator=)", parent);

	if (this == &cSource)
		return *this;

	return *this;
}
#endif

static void parse_pcr(uint8_t *pcr, uint64_t *pcr_base, unsigned int *pcr_ext)
{
	*pcr_base = ((uint64_t)pcr[0] * 0x2000000) +
		    ((uint64_t)pcr[1] * 0x20000) +
		    ((uint64_t)pcr[2] * 0x200) +
		    ((uint64_t)pcr[3] * 0x02) +
		    ((uint64_t)(pcr[4] & 0x80) >> 7);

	*pcr_ext = ((pcr[4] & 0x01) * 0x100) + pcr[5];

	return;
}

static time_t walltime(void *p) { (void)p; return time(NULL); }

char *stats_scale_unit(char *b, size_t n, uint64_t x)
{
	memset(b, 0, n);

	if (x >= 1000000) {
#if 0
		if ((x % 1000000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
		else
#endif
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
	} else if (x >= 1000) {
#if 0
		if ((x % 1000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
		else
#endif
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
	} else
		snprintf(b, n, "    %3" PRIu64 "  ", x);
	return b;
}

void stats::show(bool per_sec)
{
	if (statistics_cb) {
		statistics_cb(statistics_priv, statistics, discontinuities, tei_count, per_sec);
	}
	if (statistics_iface) {
		statistics_iface->stats(statistics, discontinuities, tei_count, per_sec);
	}
	if (statistics_cb || statistics_iface) {
		return;
	}
	for (stats_map::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter) {
		char a[16];
		char b[16];
		if (dbg & DBG_STATS) __log_printf(stderr, "pid %04x %5" PRIu64 " p%s  %sb%s  %sbit\n",
			     iter->first, iter->second / 188, (per_sec) ? "/s" : "",
			     stats_scale_unit(a, sizeof(a), iter->second), (per_sec) ? "/s" : "",
			     stats_scale_unit(b, sizeof(b), iter->second * 8));
	}
	for (stats_map::const_iterator iter = discontinuities.begin(); iter != discontinuities.end(); ++iter)
		if (dbg & DBG_STATS) __log_printf(stderr, "pid %04x\t%" PRIu64 " continuity errors (%" PRIu64 "%%)\n", iter->first, iter->second, ((!iter->second) || (!statistics[iter->first])) ? 0 : (!statistics.count(iter->first)) ? 0 : (100 * iter->second / (statistics[iter->first] / 188)));

	if ((tei_count) && (dbg & DBG_STATS)) __log_printf(stderr, "tei count: %" PRIu64 " (%" PRIu64 "%%)\n", tei_count, (!statistics[0x2000]) ? 0 : (18800 * tei_count / statistics[0x2000]));
}

void stats::push_pid(int c, const uint16_t pid)
{
	streamtime_callback cb = (streamtime_cb) ? streamtime_cb : &walltime;
	time_t timenow = cb(streamtime_priv);

	if (timenow > __timenow) {
		show();
		clear_stats();
		__timenow = timenow;
	}

	__push_pid(c, pid);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	return parse(p, pkt_stats, hdr, adapt);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats, pkt_hdr_t &hdr, adaptation_field_t &adapt)
{
	if (pkt_stats) {
		memset(pkt_stats, 0, sizeof(pkt_stats_t));

		const uint8_t *q = p;

		memset(&adapt, 0, sizeof(adapt));
		memset(&hdr, 0, sizeof(hdr));

		hdr.sync_byte          = q[0];
		hdr.tei                = (q[1] & 0x80) >> 7;
		hdr.payload_unit_start = (q[1] & 0x40) >> 6;
		hdr.transport_priority = (q[1] & 0x20) >> 5;
		hdr.pid                = ((q[1] & 0x1f) << 8) | q[2];
		hdr.scrambling         = (q[3] & 0xc0) >> 6;
		hdr.adaptation_flags   = (q[3] & 0x30) >> 4;
		hdr.continuity_ctr     = (q[3] & 0x0f);

		if (hdr.adaptation_flags & 0x02) {
			q += 4;
			adapt.field_length   = q[0];
			adapt.discontinuity  = (q[1] & 0x80) >> 7;
			adapt.random_access  = (q[1] & 0x40) >> 6; /* set to 1 if the PES pkt in this TS pkt starts an a/v sequence */
			adapt.es_priority    = (q[1] & 0x20) >> 5;
			adapt.pcr            = (q[1] & 0x10) >> 4;
			adapt.opcr           = (q[1] & 0x08) >> 3;
			adapt.splicing_point = (q[1] & 0x04) >> 2;
			adapt.tp_priv_data   = (q[1] & 0x02) >> 1;
			adapt.field_ext      = (q[1] & 0x01) >> 0;

			if (adapt.pcr) {
				memcpy(adapt.PCR, &q[2], 6);
				q += 6;
			}
			if (adapt.opcr) {
				memcpy(adapt.OPCR, &q[2], 6);
				q += 6;
			}
			if (adapt.splicing_point) {
				adapt.splicing_countdown = q[2];
				q ++;
			}
		}

		pkt_stats->sync_loss = (hdr.sync_byte != 0x47) ? true : false;
		if (!pkt_stats->sync_loss) {
			pkt_stats->tei = (hdr.tei) ? true : false;
			pkt_stats->pid = hdr.pid;
		} else
			pkt_stats->pid = (uint16_t) - 1;
	}
	return pkt_stats;
}

void stats::clear_stats()
{
	statistics.clear();
	discontinuities.clear();
	last_pcr_base.clear();
	tei_count = 0;
}

void stats::push_stats(pkt_stats_t *pkt_stats)
{
	if (pkt_stats->tei) {
		tei_count++;
		push_pid((uint16_t) - 1);
	} else
		push_pid(pkt_stats->pid);
}

void stats::push(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	if (!pkt_stats) {
		__push(p);
		return;
	}

	memset(pkt_stats, 0, sizeof(pkt_stats_t));

	parse(p, pkt_stats, hdr, adapt);

	if (hdr.adaptation_flags & 0x01) {// payload present
		if (continuity.count(hdr.pid)) {
			uint8_t next = (continuity[hdr.pid] + 1) & 0x0f;
			if ((next != (hdr.continuity_ctr & 0x0f)) && (hdr.continuity_ctr + continuity[hdr.pid] > 0)) {
				if (!(hdr.adaptation_flags & 0x02) && (adapt.discontinuity)) {
					push_discontinuity(hdr.pid);
#if DBG
					dPrintf("CONTINUITY ERROR pid: %04x cur: 0x%x prev 0x%x", hdr.pid, hdr.continuity_ctr, continuity[hdr.pid]);
#endif
				}
			}
		}
		continuity[hdr.pid] = hdr.continuity_ctr;
	}

	if (hdr.adaptation_flags & 0x02) {
		if (adapt.pcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.PCR, &pcr_base, &pcr_ext);
			if (dbg & DBG_STATS) __log_printf(stderr, "PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d\n", hdr.pid, pcr_base, pcr_ext);

#if DBG
			stats_map::const_iterator iter = last_pcr_base.find(hdr.pid);
			if ((iter != last_pcr_base.end()) && (pcr_base < iter->second))
				__log_printf(stderr, "%s: PID: 0x%04x, %" PRIu64 " < %" PRIu64 " !!!\n",
					__func__, hdr.pid, pcr_base, iter->second);
#endif
			last_pcr_base[hdr.pid] = pcr_base;
		}
		if (adapt.opcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.OPCR, &pcr_base, &pcr_ext);
			if (dbg & DBG_STATS) __log_printf(stderr, "PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d\n", hdr.pid, pcr_base, pcr_ext);
		}
		if (adapt.splicing_point) {
			dPrintf("PID: 0x%04x, splicing countdown: %d", hdr.pid, adapt.splicing_countdown);
		}
	}

	push_stats(pkt_stats);
}
<commit_msg>stats: fix stats_scale_unit() when (x % 1000000) < 1000<commit_after>/*****************************************************************************
 * Copyright (C) 2011-2016 Michael Ira Krufky
 *
 * Author: Michael Ira Krufky <mkrufky@linuxtv.org>
 *
 * This library 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 library 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <inttypes.h>
#include "string.h"

#include "stats.h"
#include "log.h"
#define CLASS_MODULE "stats"

#define DBG 0

#define dPrintf(fmt, arg...) __dPrintf(DBG_STATS, "(%s) " fmt, parent, ##arg)

stats::stats(const char *caller)
  : tei_count(0)
  , __timenow(0)
  , parent(caller)
  , streamtime_cb(NULL)
  , streamtime_priv(NULL)
  , statistics_cb(NULL)
  , statistics_priv(NULL)
  , statistics_iface(NULL)
{
	dPrintf("(%s)", parent);
}

stats::~stats()
{
	dPrintf("(%s)", parent);
	show(false);
}

#if 0
stats::stats(const stats&)
{
	dPrintf("(%s, copy)", parent);
}

stats& stats::operator= (const stats& cSource)
{
	dPrintf("(%s, operator=)", parent);

	if (this == &cSource)
		return *this;

	return *this;
}
#endif

static void parse_pcr(uint8_t *pcr, uint64_t *pcr_base, unsigned int *pcr_ext)
{
	*pcr_base = ((uint64_t)pcr[0] * 0x2000000) +
		    ((uint64_t)pcr[1] * 0x20000) +
		    ((uint64_t)pcr[2] * 0x200) +
		    ((uint64_t)pcr[3] * 0x02) +
		    ((uint64_t)(pcr[4] & 0x80) >> 7);

	*pcr_ext = ((pcr[4] & 0x01) * 0x100) + pcr[5];

	return;
}

static time_t walltime(void *p) { (void)p; return time(NULL); }

char *stats_scale_unit(char *b, size_t n, uint64_t x)
{
	memset(b, 0, n);

	if (x >= 1000000) {
#if 1
		if ((x % 1000000) < 1000)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000000);
		else
#endif
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " m", x / 1000000, x % 1000);
	} else if (x >= 1000) {
#if 0
		if ((x % 1000) < 100)
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
		else
#endif
			snprintf(b, n, "%3" PRIu64 ".%03" PRIu64 " k", x / 1000, x % 1000);
	} else
		snprintf(b, n, "    %3" PRIu64 "  ", x);
	return b;
}

void stats::show(bool per_sec)
{
	if (statistics_cb) {
		statistics_cb(statistics_priv, statistics, discontinuities, tei_count, per_sec);
	}
	if (statistics_iface) {
		statistics_iface->stats(statistics, discontinuities, tei_count, per_sec);
	}
	if (statistics_cb || statistics_iface) {
		return;
	}
	for (stats_map::const_iterator iter = statistics.begin(); iter != statistics.end(); ++iter) {
		char a[16];
		char b[16];
		if (dbg & DBG_STATS) __log_printf(stderr, "pid %04x %5" PRIu64 " p%s  %sb%s  %sbit\n",
			     iter->first, iter->second / 188, (per_sec) ? "/s" : "",
			     stats_scale_unit(a, sizeof(a), iter->second), (per_sec) ? "/s" : "",
			     stats_scale_unit(b, sizeof(b), iter->second * 8));
	}
	for (stats_map::const_iterator iter = discontinuities.begin(); iter != discontinuities.end(); ++iter)
		if (dbg & DBG_STATS) __log_printf(stderr, "pid %04x\t%" PRIu64 " continuity errors (%" PRIu64 "%%)\n", iter->first, iter->second, ((!iter->second) || (!statistics[iter->first])) ? 0 : (!statistics.count(iter->first)) ? 0 : (100 * iter->second / (statistics[iter->first] / 188)));

	if ((tei_count) && (dbg & DBG_STATS)) __log_printf(stderr, "tei count: %" PRIu64 " (%" PRIu64 "%%)\n", tei_count, (!statistics[0x2000]) ? 0 : (18800 * tei_count / statistics[0x2000]));
}

void stats::push_pid(int c, const uint16_t pid)
{
	streamtime_callback cb = (streamtime_cb) ? streamtime_cb : &walltime;
	time_t timenow = cb(streamtime_priv);

	if (timenow > __timenow) {
		show();
		clear_stats();
		__timenow = timenow;
	}

	__push_pid(c, pid);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	return parse(p, pkt_stats, hdr, adapt);
}

pkt_stats_t *stats::parse(const uint8_t *p, pkt_stats_t *pkt_stats, pkt_hdr_t &hdr, adaptation_field_t &adapt)
{
	if (pkt_stats) {
		memset(pkt_stats, 0, sizeof(pkt_stats_t));

		const uint8_t *q = p;

		memset(&adapt, 0, sizeof(adapt));
		memset(&hdr, 0, sizeof(hdr));

		hdr.sync_byte          = q[0];
		hdr.tei                = (q[1] & 0x80) >> 7;
		hdr.payload_unit_start = (q[1] & 0x40) >> 6;
		hdr.transport_priority = (q[1] & 0x20) >> 5;
		hdr.pid                = ((q[1] & 0x1f) << 8) | q[2];
		hdr.scrambling         = (q[3] & 0xc0) >> 6;
		hdr.adaptation_flags   = (q[3] & 0x30) >> 4;
		hdr.continuity_ctr     = (q[3] & 0x0f);

		if (hdr.adaptation_flags & 0x02) {
			q += 4;
			adapt.field_length   = q[0];
			adapt.discontinuity  = (q[1] & 0x80) >> 7;
			adapt.random_access  = (q[1] & 0x40) >> 6; /* set to 1 if the PES pkt in this TS pkt starts an a/v sequence */
			adapt.es_priority    = (q[1] & 0x20) >> 5;
			adapt.pcr            = (q[1] & 0x10) >> 4;
			adapt.opcr           = (q[1] & 0x08) >> 3;
			adapt.splicing_point = (q[1] & 0x04) >> 2;
			adapt.tp_priv_data   = (q[1] & 0x02) >> 1;
			adapt.field_ext      = (q[1] & 0x01) >> 0;

			if (adapt.pcr) {
				memcpy(adapt.PCR, &q[2], 6);
				q += 6;
			}
			if (adapt.opcr) {
				memcpy(adapt.OPCR, &q[2], 6);
				q += 6;
			}
			if (adapt.splicing_point) {
				adapt.splicing_countdown = q[2];
				q ++;
			}
		}

		pkt_stats->sync_loss = (hdr.sync_byte != 0x47) ? true : false;
		if (!pkt_stats->sync_loss) {
			pkt_stats->tei = (hdr.tei) ? true : false;
			pkt_stats->pid = hdr.pid;
		} else
			pkt_stats->pid = (uint16_t) - 1;
	}
	return pkt_stats;
}

void stats::clear_stats()
{
	statistics.clear();
	discontinuities.clear();
	last_pcr_base.clear();
	tei_count = 0;
}

void stats::push_stats(pkt_stats_t *pkt_stats)
{
	if (pkt_stats->tei) {
		tei_count++;
		push_pid((uint16_t) - 1);
	} else
		push_pid(pkt_stats->pid);
}

void stats::push(const uint8_t *p, pkt_stats_t *pkt_stats)
{
	adaptation_field_t adapt;
	pkt_hdr_t hdr;

	if (!pkt_stats) {
		__push(p);
		return;
	}

	memset(pkt_stats, 0, sizeof(pkt_stats_t));

	parse(p, pkt_stats, hdr, adapt);

	if (hdr.adaptation_flags & 0x01) {// payload present
		if (continuity.count(hdr.pid)) {
			uint8_t next = (continuity[hdr.pid] + 1) & 0x0f;
			if ((next != (hdr.continuity_ctr & 0x0f)) && (hdr.continuity_ctr + continuity[hdr.pid] > 0)) {
				if (!(hdr.adaptation_flags & 0x02) && (adapt.discontinuity)) {
					push_discontinuity(hdr.pid);
#if DBG
					dPrintf("CONTINUITY ERROR pid: %04x cur: 0x%x prev 0x%x", hdr.pid, hdr.continuity_ctr, continuity[hdr.pid]);
#endif
				}
			}
		}
		continuity[hdr.pid] = hdr.continuity_ctr;
	}

	if (hdr.adaptation_flags & 0x02) {
		if (adapt.pcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.PCR, &pcr_base, &pcr_ext);
			if (dbg & DBG_STATS) __log_printf(stderr, "PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d\n", hdr.pid, pcr_base, pcr_ext);

#if DBG
			stats_map::const_iterator iter = last_pcr_base.find(hdr.pid);
			if ((iter != last_pcr_base.end()) && (pcr_base < iter->second))
				__log_printf(stderr, "%s: PID: 0x%04x, %" PRIu64 " < %" PRIu64 " !!!\n",
					__func__, hdr.pid, pcr_base, iter->second);
#endif
			last_pcr_base[hdr.pid] = pcr_base;
		}
		if (adapt.opcr) {
			uint64_t pcr_base;
			unsigned int pcr_ext;

			parse_pcr(adapt.OPCR, &pcr_base, &pcr_ext);
			if (dbg & DBG_STATS) __log_printf(stderr, "PID: 0x%04x, PCR base: %" PRIu64 ", ext: %d\n", hdr.pid, pcr_base, pcr_ext);
		}
		if (adapt.splicing_point) {
			dPrintf("PID: 0x%04x, splicing countdown: %d", hdr.pid, adapt.splicing_countdown);
		}
	}

	push_stats(pkt_stats);
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 Josh A. Beam
 * 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 AUTHOR ``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 AUTHOR 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 CONTACT, 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 <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <xviweb/String.h>
#include "FileResponder.h"

using namespace std;

FileResponder::FileResponder()
{
	m_rootDirectory = ".";

	// add some standard MIME types
	addMimeType("text/plain", "txt");
	addMimeType("text/html", "html");
	addMimeType("text/css", "css");
	addMimeType("text/javascript", "js");
	addMimeType("image/png", "png");
	addMimeType("image/jpg", "jpeg");
	addMimeType("image/jpg", "jpg");
	addMimeType("image/gif", "gif");
}

FileResponder::~FileResponder()
{
}

void
FileResponder::addOption(const string &option, const string &value)
{
	if(option == "rootDirectory") {
		m_rootDirectory = value;
	} else if(option == "mimeType") {
		vector <string> values = String::split(value, ";");
		if(values.size() == 2) {
			m_mimeTypes.push_back(values[0]);
			m_mimeFileExtensions.push_back(string(".") + values[1]);
		}
	}
}

void
FileResponder::addMimeType(const string &mimeType, const string &fileExtension)
{
	addOption("mimeType", mimeType + ";" + fileExtension);
}

string
FileResponder::getMimeTypeForFile(const string &path) const
{
	// find the type associated with the file extension
	for(unsigned int i = 0; i < m_mimeTypes.size(); ++i) {
		if(String::endsWith(path, m_mimeFileExtensions[i], true))
			return m_mimeTypes[i];
	}

	return string("");
}

static string
mapPath(const string &path)
{
	// not confident that the commented out code below
	// works right yet, so just return an empty string
	// if the requested path contains a ..
	if(path.find("..") != string::npos)
		return string("");

	string newPath = path;

	// replace back slashes with forward slashes
	size_t tmp;
	while((tmp = newPath.find('\\')) != string::npos)
		newPath[tmp] = '/';

	// replace double slashes with single slashes
	while((tmp = newPath.find("//")) != string::npos)
		newPath.erase(tmp, 1);

#if 0
	// make sure .. isn't used to go above the root directory
	int depth = 0;
	for(int i = 0; i < (int)newPath.length() - 3; ++i) {
		if(newPath[i] == '/') {
			if(newPath[i+1] == '.' && newPath[i+2] == '.' && newPath[i+3] == '/') {
				if(--depth < 0)
					return string("");
				i += 3;
			} else {
				++depth;
			}
		}
	}
#endif

	return newPath;
}

bool
FileResponder::matchesRequest(const HttpRequest * /*request*/) const
{
	return true;
}

ResponderContext *
FileResponder::respond(const HttpRequest *request, HttpResponse *response)
{
	// if the path returned by mapPath has a length
	// of zero, the path requested is invalid
	string path = mapPath(request->getPath());
	if(path.length() == 0) {
		response->sendErrorResponse(403, "Forbidden", "The provided file path is invalid.");
		return NULL;
	}

	path = request->getVHostRoot() + path;

	// open the file and get its status
	struct stat status;
	int fd = open(path.c_str(), O_RDONLY);
	if(fd == -1 || fstat(fd, &status) == -1) {
		if(fd != -1)
			close(fd);
		response->sendErrorResponse(404, "File Not Found", "The file that you requested does not exist.");
		return NULL;
	}

	// don't show directory listings
	if(S_ISDIR(status.st_mode)) {
		close(fd);
		response->sendErrorResponse(403, "Forbidden", "You do not have access to directory listings.");
		return NULL;
	}

	// get the MIME type for the file; if there's no
	// MIME type associated with the file extension,
	// just refuse to serve the file for security reasons
	string contentType = getMimeTypeForFile(path);
	if(contentType.length() == 0) {
		close(fd);
		response->sendErrorResponse(403, "Forbidden", "You do not have access to files of this type.");
		return NULL;
	}

	response->setStatus(200, "OK");
	response->setContentType(contentType);
	response->setContentLength((int)status.st_size);

	if(request->getVerb() != "HEAD") {
		// read the file and send it to the client
		char buf[512];
		ssize_t length;
		while((length = read(fd, buf, sizeof(buf))) > 0)
			response->sendString(buf, length);
	}

	response->endResponse();

	close(fd);
	return NULL;
}

XVIWEB_RESPONDER(FileResponder);
<commit_msg>Added support for index.html as a default document.<commit_after>/*
 * Copyright (C) 2011 Josh A. Beam
 * 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 AUTHOR ``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 AUTHOR 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 CONTACT, 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 <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <xviweb/String.h>
#include "FileResponder.h"

using namespace std;

FileResponder::FileResponder()
{
	m_rootDirectory = ".";

	// add some standard MIME types
	addMimeType("text/plain", "txt");
	addMimeType("text/html", "html");
	addMimeType("text/css", "css");
	addMimeType("text/javascript", "js");
	addMimeType("image/png", "png");
	addMimeType("image/jpg", "jpeg");
	addMimeType("image/jpg", "jpg");
	addMimeType("image/gif", "gif");
}

FileResponder::~FileResponder()
{
}

void
FileResponder::addOption(const string &option, const string &value)
{
	if(option == "rootDirectory") {
		m_rootDirectory = value;
	} else if(option == "mimeType") {
		vector <string> values = String::split(value, ";");
		if(values.size() == 2) {
			m_mimeTypes.push_back(values[0]);
			m_mimeFileExtensions.push_back(string(".") + values[1]);
		}
	}
}

void
FileResponder::addMimeType(const string &mimeType, const string &fileExtension)
{
	addOption("mimeType", mimeType + ";" + fileExtension);
}

string
FileResponder::getMimeTypeForFile(const string &path) const
{
	// find the type associated with the file extension
	for(unsigned int i = 0; i < m_mimeTypes.size(); ++i) {
		if(String::endsWith(path, m_mimeFileExtensions[i], true))
			return m_mimeTypes[i];
	}

	return string("");
}

static string
mapPath(const string &path)
{
	// not confident that the commented out code below
	// works right yet, so just return an empty string
	// if the requested path contains a ..
	if(path.find("..") != string::npos)
		return string("");

	string newPath = path;

	// replace back slashes with forward slashes
	size_t tmp;
	while((tmp = newPath.find('\\')) != string::npos)
		newPath[tmp] = '/';

	// replace double slashes with single slashes
	while((tmp = newPath.find("//")) != string::npos)
		newPath.erase(tmp, 1);

#if 0
	// make sure .. isn't used to go above the root directory
	int depth = 0;
	for(int i = 0; i < (int)newPath.length() - 3; ++i) {
		if(newPath[i] == '/') {
			if(newPath[i+1] == '.' && newPath[i+2] == '.' && newPath[i+3] == '/') {
				if(--depth < 0)
					return string("");
				i += 3;
			} else {
				++depth;
			}
		}
	}
#endif

	return newPath;
}

bool
FileResponder::matchesRequest(const HttpRequest * /*request*/) const
{
	return true;
}

ResponderContext *
FileResponder::respond(const HttpRequest *request, HttpResponse *response)
{
	// if the path returned by mapPath has a length
	// of zero, the path requested is invalid
	string path = mapPath(request->getPath());
	if(path.length() == 0) {
		response->sendErrorResponse(403, "Forbidden", "The provided file path is invalid.");
		return NULL;
	}

	path = request->getVHostRoot() + path;

	// open the file and get its status
	struct stat status;
	int fd = open(path.c_str(), O_RDONLY);
	if(fd == -1 || fstat(fd, &status) == -1) {
		if(fd != -1)
			close(fd);
		response->sendErrorResponse(404, "File Not Found", "The file that you requested does not exist.");
		return NULL;
	}

	// don't show directory listings
	if(S_ISDIR(status.st_mode)) {
		close(fd);

		// see if an index.html exists in the directory;
		// if not, show an error message
		path += "/index.html";
		fd = open(path.c_str(), O_RDONLY);
		if(fd == -1 || fstat(fd, &status) == -1 || S_ISDIR(status.st_mode)) {
			if(fd != -1)
				close(fd);
			response->sendErrorResponse(403, "Forbidden", "You do not have access to directory listings.");
			return NULL;
		}
	}

	// get the MIME type for the file; if there's no
	// MIME type associated with the file extension,
	// just refuse to serve the file for security reasons
	string contentType = getMimeTypeForFile(path);
	if(contentType.length() == 0) {
		close(fd);
		response->sendErrorResponse(403, "Forbidden", "You do not have access to files of this type.");
		return NULL;
	}

	response->setStatus(200, "OK");
	response->setContentType(contentType);
	response->setContentLength((int)status.st_size);

	if(request->getVerb() != "HEAD") {
		// read the file and send it to the client
		char buf[512];
		ssize_t length;
		while((length = read(fd, buf, sizeof(buf))) > 0)
			response->sendString(buf, length);
	}

	response->endResponse();

	close(fd);
	return NULL;
}

XVIWEB_RESPONDER(FileResponder);
<|endoftext|>


<commit_before>//
//  File:       EventBus.hpp
//  Class:      EventBus
//  Author:     Jesper Persson and Sebastian Odbjer
//              All code is our own except where credited to others.
//
//	Copyright (c) 2012 by Catch22. All Rights Reserved.
//  Date: 		02/10-2012
//
//	License: The following code is licensed under the Catch22-License
//
<commit_msg>Implemented basic structure of chainsaw<commit_after>//
//  File:       EventBus.hpp
//  Class:      EventBus
//  Author:     Jesper Persson and Sebastian Odbjer
//              All code is our own except where credited to others.
//
//	Copyright (c) 2012 by Catch22. All Rights Reserved.
//  Date: 		02/10-2012
//
//	License: The following code is licensed under the Catch22-License
//

#include "Chainsaw.hpp"
#include "../../EventHandling/EventBus.hpp"
#include "../../EventHandling/EEvent.hpp"

Chainsaw::Chainsaw (b2Vec2 size, b2Vec2 position,b2Vec2 target,  bool stationary, bool rotatable, PBodyType tag) :
    PBody(size, position, stationary, rotatable, tag)
{
    m_target = target;
    m_targetReached = false;
    EventBus::getSharedInstance()->publishEvent(PBODY_CREATED_PHYSICS, this);
}

bool Chainsaw::targetReached()
{
    return m_targetReached;
}

void Chainsaw::setTarget(b2Vec2 target)
{
    m_target = target;
}

<|endoftext|>


<commit_before>//==============================================================================
// CellMLTools plugin
//==============================================================================

#include "cellmlfilemanager.h"
#include "cellmlsupportplugin.h"
#include "cellmltoolsplugin.h"
#include "coreutils.h"

//==============================================================================

#include <QAction>
#include <QFileInfo>
#include <QMainWindow>
#include <QMenu>
#include <QMessageBox>

//==============================================================================

namespace OpenCOR {
namespace CellMLTools {

//==============================================================================

PLUGININFO_FUNC CellMLToolsPluginInfo()
{
    Descriptions descriptions;

    descriptions.insert("en", QString::fromUtf8("a plugin to access various CellML-related tools."));
    descriptions.insert("fr", QString::fromUtf8("une extension pour accéder à divers outils en rapport avec CellML."));

    return new PluginInfo(PluginInfo::InterfaceVersion001,
                          PluginInfo::Miscellaneous,
                          true,
                          true,
                          QStringList() << "CellMLSupport",
                          descriptions);
}

//==============================================================================

void CellMLToolsPlugin::initialize()
{
    // Create our Tools | Export To menu

    mCellmlFileExportToMenu = newMenu(mMainWindow, "CellmlFileExportTo");

    // Create our different Tools | Export To actions, and add them to our
    // Tools | Export To menu

    mExportToCellml10Action = newAction(mMainWindow);
    mExportToCellml11Action = newAction(mMainWindow);

    mCellmlFileExportToMenu->addAction(mExportToCellml10Action);
    mCellmlFileExportToMenu->addAction(mExportToCellml11Action);

    // Some connections to handle our different Tools | Export To actions

    connect(mExportToCellml10Action, SIGNAL(triggered()),
            this, SLOT(exportToCellml10()));
    connect(mExportToCellml11Action, SIGNAL(triggered()),
            this, SLOT(exportToCellml11()));

    // Set our settings

    mGuiSettings->addMenuAction(GuiMenuActionSettings::Tools, mCellmlFileExportToMenu->menuAction());
    mGuiSettings->addMenuAction(GuiMenuActionSettings::Tools);
}

//==============================================================================

void CellMLToolsPlugin::initializationsDone(const Plugins &pLoadedPlugins)
{
    // Retrieve the file types supported by the CellMLSupport plugin

    mCellmlFileTypes = FileTypes();

    foreach (Plugin *loadedPlugin, pLoadedPlugins) {
        FileInterface *fileInterface = qobject_cast<FileInterface *>(loadedPlugin->instance());

        if (!loadedPlugin->name().compare("CellMLSupport") && fileInterface) {
            // This is the CellMLSupport plugin and, as expected, it implements
            // the file interface, so retrieve the file types it supports

            mCellmlFileTypes = fileInterface->fileTypes();

            break;
        }
    }
}

//==============================================================================

void CellMLToolsPlugin::runHelpCommand()
{
    std::cout << "Commands supported by CellMLTools:" << std::endl;
    std::cout << " * Display the commands supported by CellMLTools:" << std::endl;
    std::cout << "      help" << std::endl;
    std::cout << " * Export <in_file> to <out_file> using <format> as the destination format:" << std::endl;
    std::cout << "      export <in_file> <out_file> <format>" << std::endl;
    std::cout << "   <format> can take one of the following values:" << std::endl;
    std::cout << "      cellml_1_0: to export a CellML 1.1 file to CellML 1.0" << std::endl;
}

//==============================================================================

void CellMLToolsPlugin::runExportCommand(const QStringList &pArguments,
                                         int *pRes)
{
    // Export an existing file to another file using a given format as the
    // destination format

    // Make sure that we have three arguments and that the given format is
    // valid

    bool validArguments = true;

    if (pArguments.count() != 3) {
        validArguments = false;
    } else {
        QString format = pArguments.at(2);

        if (format.compare("cellml_1_0"))
            validArguments = false;
    }

    // Confirm that we have valid arguments

    if (!validArguments) {
        runHelpCommand();

        *pRes = -1;

        return;
    }

    // Make sure that the input file exists and that it is a valid non CellML
    // 1.0 file

    QString errorMessage = QString();
    QString inFileName = pArguments.at(0);
    CellMLSupport::CellmlFile *inCellmlFile = new CellMLSupport::CellmlFile(inFileName);

    if (!QFileInfo(inFileName).exists())
        errorMessage = "Sorry, but the input file could not be found.";
    else if (!CellMLSupport::isCellmlFile(inFileName))
        errorMessage = "Sorry, but the input file is not a CellML file.";
    else if (!inCellmlFile->load())
        errorMessage = "Sorry, but a problem occurred while loading the input file.";
    else if (!QString::fromStdWString(inCellmlFile->model()->cellmlVersion()).compare(CellMLSupport::Cellml_1_0))
        errorMessage = "Sorry, but the input file is already a CellML 1.0 file.";

    // Our input file is a valid non CellML 1.0 file, so we can export it to
    // CellML 1.0

    if (    errorMessage.isEmpty()
        && !inCellmlFile->exportTo(pArguments.at(1), CellMLSupport::CellmlFile::Cellml_1_0))
        errorMessage = "Sorry, but a problem occurred while exporting the input file.";

    delete inCellmlFile;

    // Check whether something wrong happened at some point

    if (!errorMessage.isEmpty()) {
        std::cout << qPrintable(errorMessage) << std::endl;

        *pRes = -1;
    }
}

//==============================================================================

void CellMLToolsPlugin::runCliCommand(const QString &pCommand,
                                      const QStringList &pArguments, int *pRes)
{
    // Run the given CLI command

    *pRes = 0;

    if (!pCommand.compare("help")) {
        // Display the commands we support

        runHelpCommand();
    } else if (!pCommand.compare("export")) {
        // Export a file from one format to another

        runExportCommand(pArguments, pRes);
    } else {
        // Not a CLI command that we can run, so...

        runHelpCommand();

        *pRes = -1;
    }
}

//==============================================================================

void CellMLToolsPlugin::updateGui(Plugin *pViewPlugin, const QString &pFileName)
{
    // Enable/disable and show/hide our tools in case we are dealing with a
    // CellML-based view plugin

    bool toolsVisible = pViewPlugin?
                            pViewPlugin->info()->fullDependencies().contains("CellMLSupport"):
                            false;
    CellMLSupport::CellmlFile *cellmlFile = CellMLSupport::CellmlFileManager::instance()->cellmlFile(pFileName);

    mCellmlFileExportToMenu->menuAction()->setEnabled(toolsVisible);
    mCellmlFileExportToMenu->menuAction()->setVisible(toolsVisible);

    mExportToCellml10Action->setEnabled(   toolsVisible && cellmlFile
                                        && QString::fromStdWString(cellmlFile->model()->cellmlVersion()).compare(CellMLSupport::Cellml_1_0));
    mExportToCellml10Action->setVisible(toolsVisible);

/*---GRY---
    mExportToCellml11Action->setEnabled(   toolsVisible && cellmlFile
                                        && QString::fromStdWString(cellmlFile->model()->cellmlVersion()).compare(CellMLSupport::Cellml_1_1));
    mExportToCellml11Action->setVisible(toolsVisible);
*/
//---GRY--- BEGIN
// THIS IS UNTIL EXPORTING TO CellML 1.1 IS FULLY SUPPORTED...
mExportToCellml11Action->setEnabled(false);
mExportToCellml11Action->setVisible(false);
//---GRY--- END

    // Keep track of the file name

    mFileName = pFileName;
}

//==============================================================================

void CellMLToolsPlugin::retranslateUi()
{
    // Retranslate our different Tools actions

    retranslateMenu(mCellmlFileExportToMenu, tr("CellML File Export To"));

    retranslateAction(mExportToCellml10Action, tr("CellML 1.0..."), tr("Export the CellML file to CellML 1.0"));
    retranslateAction(mExportToCellml11Action, tr("CellML 1.1..."), tr("Export the CellML file to CellML 1.1"));
}

//==============================================================================

void CellMLToolsPlugin::exportTo(const CellMLSupport::CellmlFile::Format &pFormat)
{
    // Ask for the name of the file which will contain the export

    QString format;
    QString fileTypes;

    switch (pFormat) {
    case CellMLSupport::CellmlFile::Cellml_1_1:
    default:   // CellMLSupport::CellmlFile::Cellml_1_0
        if (pFormat == CellMLSupport::CellmlFile::Cellml_1_0)
            format = "CellML 1.0";
        else
            format = "CellML 1.1";

        foreach (const FileType &fileType, mCellmlFileTypes) {
            if (!fileTypes.isEmpty())
                fileTypes += ";;";

            fileTypes +=  fileType.description()+" (*."+fileType.fileExtension()+")";
        }
    }

    QString fileName = Core::getSaveFileName(tr("CellML file export to %1").arg(format), mFileName, fileTypes);

    // Make sure that we have a file name or leave, if not

    if (fileName.isEmpty())
        return;

    // Now that we have a file name, we can do the eport itself

    CellMLSupport::CellmlFile *cellmlFile = CellMLSupport::CellmlFileManager::instance()->cellmlFile(mFileName);

    if (!cellmlFile->exportTo(fileName, pFormat)) {
        CellMLSupport::CellmlFileIssues issues = cellmlFile->issues();
        QString errorMessage = QString();

        if (issues.count())
            errorMessage = " ("+issues.first().message()+")";
            // Note: if there are 'issues', then there can be only one of them
            //       following a CellML export...

        QMessageBox::warning(mMainWindow, tr("CellML file export to %1").arg(format),
                             tr("Sorry, but %1 could not be exported to %2%3.").arg(fileName, format, errorMessage));
    }
}

//==============================================================================

void CellMLToolsPlugin::exportToCellml10()
{
    // Export the current file to CellML 1.0

    exportTo(CellMLSupport::CellmlFile::Cellml_1_0);
}

//==============================================================================

void CellMLToolsPlugin::exportToCellml11()
{
    // Export the current file to CellML 1.1

    exportTo(CellMLSupport::CellmlFile::Cellml_1_1);
}

//==============================================================================

}   // namespace CellMLSupport
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>CellMLTools plugin: enable/disable our CellML File Export menu based depending on whether some exports are enabled.<commit_after>//==============================================================================
// CellMLTools plugin
//==============================================================================

#include "cellmlfilemanager.h"
#include "cellmlsupportplugin.h"
#include "cellmltoolsplugin.h"
#include "coreutils.h"

//==============================================================================

#include <QAction>
#include <QFileInfo>
#include <QMainWindow>
#include <QMenu>
#include <QMessageBox>

//==============================================================================

namespace OpenCOR {
namespace CellMLTools {

//==============================================================================

PLUGININFO_FUNC CellMLToolsPluginInfo()
{
    Descriptions descriptions;

    descriptions.insert("en", QString::fromUtf8("a plugin to access various CellML-related tools."));
    descriptions.insert("fr", QString::fromUtf8("une extension pour accéder à divers outils en rapport avec CellML."));

    return new PluginInfo(PluginInfo::InterfaceVersion001,
                          PluginInfo::Miscellaneous,
                          true,
                          true,
                          QStringList() << "CellMLSupport",
                          descriptions);
}

//==============================================================================

void CellMLToolsPlugin::initialize()
{
    // Create our Tools | Export To menu

    mCellmlFileExportToMenu = newMenu(mMainWindow, "CellmlFileExportTo");

    // Create our different Tools | Export To actions, and add them to our
    // Tools | Export To menu

    mExportToCellml10Action = newAction(mMainWindow);
    mExportToCellml11Action = newAction(mMainWindow);

    mCellmlFileExportToMenu->addAction(mExportToCellml10Action);
    mCellmlFileExportToMenu->addAction(mExportToCellml11Action);

    // Some connections to handle our different Tools | Export To actions

    connect(mExportToCellml10Action, SIGNAL(triggered()),
            this, SLOT(exportToCellml10()));
    connect(mExportToCellml11Action, SIGNAL(triggered()),
            this, SLOT(exportToCellml11()));

    // Set our settings

    mGuiSettings->addMenuAction(GuiMenuActionSettings::Tools, mCellmlFileExportToMenu->menuAction());
    mGuiSettings->addMenuAction(GuiMenuActionSettings::Tools);
}

//==============================================================================

void CellMLToolsPlugin::initializationsDone(const Plugins &pLoadedPlugins)
{
    // Retrieve the file types supported by the CellMLSupport plugin

    mCellmlFileTypes = FileTypes();

    foreach (Plugin *loadedPlugin, pLoadedPlugins) {
        FileInterface *fileInterface = qobject_cast<FileInterface *>(loadedPlugin->instance());

        if (!loadedPlugin->name().compare("CellMLSupport") && fileInterface) {
            // This is the CellMLSupport plugin and, as expected, it implements
            // the file interface, so retrieve the file types it supports

            mCellmlFileTypes = fileInterface->fileTypes();

            break;
        }
    }
}

//==============================================================================

void CellMLToolsPlugin::runHelpCommand()
{
    std::cout << "Commands supported by CellMLTools:" << std::endl;
    std::cout << " * Display the commands supported by CellMLTools:" << std::endl;
    std::cout << "      help" << std::endl;
    std::cout << " * Export <in_file> to <out_file> using <format> as the destination format:" << std::endl;
    std::cout << "      export <in_file> <out_file> <format>" << std::endl;
    std::cout << "   <format> can take one of the following values:" << std::endl;
    std::cout << "      cellml_1_0: to export a CellML 1.1 file to CellML 1.0" << std::endl;
}

//==============================================================================

void CellMLToolsPlugin::runExportCommand(const QStringList &pArguments,
                                         int *pRes)
{
    // Export an existing file to another file using a given format as the
    // destination format

    // Make sure that we have three arguments and that the given format is
    // valid

    bool validArguments = true;

    if (pArguments.count() != 3) {
        validArguments = false;
    } else {
        QString format = pArguments.at(2);

        if (format.compare("cellml_1_0"))
            validArguments = false;
    }

    // Confirm that we have valid arguments

    if (!validArguments) {
        runHelpCommand();

        *pRes = -1;

        return;
    }

    // Make sure that the input file exists and that it is a valid non CellML
    // 1.0 file

    QString errorMessage = QString();
    QString inFileName = pArguments.at(0);
    CellMLSupport::CellmlFile *inCellmlFile = new CellMLSupport::CellmlFile(inFileName);

    if (!QFileInfo(inFileName).exists())
        errorMessage = "Sorry, but the input file could not be found.";
    else if (!CellMLSupport::isCellmlFile(inFileName))
        errorMessage = "Sorry, but the input file is not a CellML file.";
    else if (!inCellmlFile->load())
        errorMessage = "Sorry, but a problem occurred while loading the input file.";
    else if (!QString::fromStdWString(inCellmlFile->model()->cellmlVersion()).compare(CellMLSupport::Cellml_1_0))
        errorMessage = "Sorry, but the input file is already a CellML 1.0 file.";

    // Our input file is a valid non CellML 1.0 file, so we can export it to
    // CellML 1.0

    if (    errorMessage.isEmpty()
        && !inCellmlFile->exportTo(pArguments.at(1), CellMLSupport::CellmlFile::Cellml_1_0))
        errorMessage = "Sorry, but a problem occurred while exporting the input file.";

    delete inCellmlFile;

    // Check whether something wrong happened at some point

    if (!errorMessage.isEmpty()) {
        std::cout << qPrintable(errorMessage) << std::endl;

        *pRes = -1;
    }
}

//==============================================================================

void CellMLToolsPlugin::runCliCommand(const QString &pCommand,
                                      const QStringList &pArguments, int *pRes)
{
    // Run the given CLI command

    *pRes = 0;

    if (!pCommand.compare("help")) {
        // Display the commands we support

        runHelpCommand();
    } else if (!pCommand.compare("export")) {
        // Export a file from one format to another

        runExportCommand(pArguments, pRes);
    } else {
        // Not a CLI command that we can run, so...

        runHelpCommand();

        *pRes = -1;
    }
}

//==============================================================================

void CellMLToolsPlugin::updateGui(Plugin *pViewPlugin, const QString &pFileName)
{
    // Enable/disable and show/hide our tools in case we are dealing with a
    // CellML-based view plugin

    bool toolsVisible = pViewPlugin?
                            pViewPlugin->info()->fullDependencies().contains("CellMLSupport"):
                            false;
    CellMLSupport::CellmlFile *cellmlFile = CellMLSupport::CellmlFileManager::instance()->cellmlFile(pFileName);

    mExportToCellml10Action->setEnabled(   toolsVisible && cellmlFile
                                        && QString::fromStdWString(cellmlFile->model()->cellmlVersion()).compare(CellMLSupport::Cellml_1_0));
    mExportToCellml10Action->setVisible(toolsVisible);

/*---GRY---
    mExportToCellml11Action->setEnabled(   toolsVisible && cellmlFile
                                        && QString::fromStdWString(cellmlFile->model()->cellmlVersion()).compare(CellMLSupport::Cellml_1_1));
    mExportToCellml11Action->setVisible(toolsVisible);
*/
//---GRY--- BEGIN
// THIS IS UNTIL EXPORTING TO CellML 1.1 IS FULLY SUPPORTED...
mExportToCellml11Action->setEnabled(false);
mExportToCellml11Action->setVisible(false);
//---GRY--- END

    bool menuEnabled = true;

    foreach (QAction *action, mCellmlFileExportToMenu->actions())
        if (!action->isEnabled()) {
            menuEnabled = false;

            break;
        }

    mCellmlFileExportToMenu->menuAction()->setEnabled(menuEnabled);
    mCellmlFileExportToMenu->menuAction()->setVisible(toolsVisible);

    // Keep track of the file name

    mFileName = pFileName;
}

//==============================================================================

void CellMLToolsPlugin::retranslateUi()
{
    // Retranslate our different Tools actions

    retranslateMenu(mCellmlFileExportToMenu, tr("CellML File Export To"));

    retranslateAction(mExportToCellml10Action, tr("CellML 1.0..."), tr("Export the CellML file to CellML 1.0"));
    retranslateAction(mExportToCellml11Action, tr("CellML 1.1..."), tr("Export the CellML file to CellML 1.1"));
}

//==============================================================================

void CellMLToolsPlugin::exportTo(const CellMLSupport::CellmlFile::Format &pFormat)
{
    // Ask for the name of the file which will contain the export

    QString format;
    QString fileTypes;

    switch (pFormat) {
    case CellMLSupport::CellmlFile::Cellml_1_1:
    default:   // CellMLSupport::CellmlFile::Cellml_1_0
        if (pFormat == CellMLSupport::CellmlFile::Cellml_1_0)
            format = "CellML 1.0";
        else
            format = "CellML 1.1";

        foreach (const FileType &fileType, mCellmlFileTypes) {
            if (!fileTypes.isEmpty())
                fileTypes += ";;";

            fileTypes +=  fileType.description()+" (*."+fileType.fileExtension()+")";
        }
    }

    QString fileName = Core::getSaveFileName(tr("CellML file export to %1").arg(format), mFileName, fileTypes);

    // Make sure that we have a file name or leave, if not

    if (fileName.isEmpty())
        return;

    // Now that we have a file name, we can do the eport itself

    CellMLSupport::CellmlFile *cellmlFile = CellMLSupport::CellmlFileManager::instance()->cellmlFile(mFileName);

    if (!cellmlFile->exportTo(fileName, pFormat)) {
        CellMLSupport::CellmlFileIssues issues = cellmlFile->issues();
        QString errorMessage = QString();

        if (issues.count())
            errorMessage = " ("+issues.first().message()+")";
            // Note: if there are 'issues', then there can be only one of them
            //       following a CellML export...

        QMessageBox::warning(mMainWindow, tr("CellML file export to %1").arg(format),
                             tr("Sorry, but %1 could not be exported to %2%3.").arg(fileName, format, errorMessage));
    }
}

//==============================================================================

void CellMLToolsPlugin::exportToCellml10()
{
    // Export the current file to CellML 1.0

    exportTo(CellMLSupport::CellmlFile::Cellml_1_0);
}

//==============================================================================

void CellMLToolsPlugin::exportToCellml11()
{
    // Export the current file to CellML 1.1

    exportTo(CellMLSupport::CellmlFile::Cellml_1_1);
}

//==============================================================================

}   // namespace CellMLSupport
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>#include "LinearRegression.h"
#include <armadillo>
#include <iostream>

LinearRegression::LinearRegression(arma::mat *x, arma::vec *y, arma::uword m)
    : y{y}, m{m}, trained{false} {
      //Create Bias Layer and append at the end of  x
      arma::mat bias = ones<arma::mat>(m,2);
      this->x = x->insert(x->n_cols ,bias);
    }

LinearRegression::~LinearRegression() {
  delete x;
  delete y;
  delete w;
}

void LinearRegression::AddData(double x[], double y[]) {
  // TODO:
  delete this->w;
  this->trained = false;
}

void LinearRegression::Train() {
  arma::mat xtx = (this->x->t() * (*this->x));
  // Check if xtx is full-rank matrix
  if (rank(xtx) == this->m) {
    this->w = new arma::mat(inv(xtx) * this->x->t() * *y);
    this->trained = true;
  } else {
    std::cerr << "you have to regularize your data set" << std::endl;
  }
}

double LinearRegression::Predict(arma::vec *x) {
  if (!this->trained) {
    std::cerr << "This model hasn't been trained" << std::endl;
    return 0.0;
  }
  return ((*this->w) * (*x)).eval()(0, 0);
}
<commit_msg>fixed typo<commit_after>#include "LinearRegression.h"
#include <armadillo>
#include <iostream>

LinearRegression::LinearRegression(arma::mat *x, arma::vec *y, arma::uword m)
    : y{y}, m{m}, trained{false} {
      //Create Bias Layer and append at the end of  x
      arma::mat bias = arma::ones<arma::mat>(m,2);
      this->x = x->arma::insert_cols(x->n_cols, bias);
    }

LinearRegression::~LinearRegression() {
  delete x;
  delete y;
  delete w;
}

void LinearRegression::AddData(double x[], double y[]) {
  // TODO:
  delete this->w;
  this->trained = false;
}

void LinearRegression::Train() {
  arma::mat xtx = (this->x->t() * (*this->x));
  // Check if xtx is full-rank matrix
  if (rank(xtx) == this->m) {
    this->w = new arma::mat(inv(xtx) * this->x->t() * *y);
    this->trained = true;
  } else {
    std::cerr << "you have to regularize your data set" << std::endl;
  }
}

double LinearRegression::Predict(arma::vec *x) {
  if (!this->trained) {
    std::cerr << "This model hasn't been trained" << std::endl;
    return 0.0;
  }
  return ((*this->w) * (*x)).eval()(0, 0);
}
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkImageStatisticsCalculationThread.h"

//QT headers
#include <QMessageBox>
#include <QApplication>

QmitkImageStatisticsCalculationThread::QmitkImageStatisticsCalculationThread():QThread(),
  m_StatisticsImage(NULL), m_BinaryMask(NULL), m_PlanarFigureMask(NULL), m_TimeStep(0),
  m_IgnoreZeros(false), m_CalculationSuccessful(false), m_StatisticChanged(false)
{
}

QmitkImageStatisticsCalculationThread::~QmitkImageStatisticsCalculationThread()
{
}

void QmitkImageStatisticsCalculationThread::Initialize( mitk::Image::Pointer image, mitk::Image::Pointer binaryImage, mitk::PlanarFigure::Pointer planarFig )
{
  // reset old values
  if( this->m_StatisticsImage.IsNotNull() )
    this->m_StatisticsImage = 0;

  if( this->m_BinaryMask.IsNotNull() )
    this->m_BinaryMask = 0;

  if( this->m_PlanarFigureMask.IsNotNull())
    this->m_PlanarFigureMask = 0;

  // set new values if passed in
  if(image.IsNotNull())
    this->m_StatisticsImage = image->Clone();
  if(binaryImage.IsNotNull())
    this->m_BinaryMask = binaryImage->Clone();
  if(planarFig.IsNotNull())
    this->m_PlanarFigureMask = dynamic_cast<mitk::PlanarFigure*>(planarFig.GetPointer()); // once clone methods for planar figures are implemented, copy the data here!
}

void QmitkImageStatisticsCalculationThread::SetTimeStep( int times )
{
  this->m_TimeStep = times;
}

int QmitkImageStatisticsCalculationThread::GetTimeStep()
{
  return this->m_TimeStep;
}

mitk::ImageStatisticsCalculator::Statistics QmitkImageStatisticsCalculationThread::GetStatisticsData()
{
  return this->m_StatisticsStruct;
}

mitk::Image::Pointer QmitkImageStatisticsCalculationThread::GetStatisticsImage()
{
  return this->m_StatisticsImage;
}

void QmitkImageStatisticsCalculationThread::SetIgnoreZeroValueVoxel(bool _arg)
{
  this->m_IgnoreZeros = _arg;
}

bool QmitkImageStatisticsCalculationThread::GetIgnoreZeroValueVoxel()
{
  return this->m_IgnoreZeros;
}

std::string QmitkImageStatisticsCalculationThread::GetLastErrorMessage()
{
  return m_message;
}

QmitkImageStatisticsCalculationThread::HistogramType::Pointer
QmitkImageStatisticsCalculationThread::GetTimeStepHistogram()
{
  return this->m_TimeStepHistogram;
}

bool QmitkImageStatisticsCalculationThread::GetStatisticsChangedFlag()
{
  return m_StatisticChanged;
}

bool QmitkImageStatisticsCalculationThread::GetStatisticsUpdateSuccessFlag()
{
  return m_CalculationSuccessful;
}

void QmitkImageStatisticsCalculationThread::run()
{
  bool statisticCalculationSuccessful = true;
  mitk::ImageStatisticsCalculator::Pointer calculator = mitk::ImageStatisticsCalculator::New();

  if(this->m_StatisticsImage.IsNotNull())
  {
    calculator->SetImage(m_StatisticsImage);
    calculator->SetMaskingModeToNone();
  }
  else
  {
    statisticCalculationSuccessful = false;
  }

  // Bug 13416 : The ImageStatistics::SetImageMask() method can throw exceptions, i.e. when the dimensionality
  // of the masked and input image differ, we need to catch them and mark the calculation as failed
  // the same holds for the ::SetPlanarFigure()
  try
  {
    if(this->m_BinaryMask.IsNotNull())
    {

      calculator->SetImageMask(m_BinaryMask);
      calculator->SetMaskingModeToImage();
    }
    if(this->m_PlanarFigureMask.IsNotNull())
    {
      calculator->SetPlanarFigure(m_PlanarFigureMask);
      calculator->SetMaskingModeToPlanarFigure();
    }
  }
  catch( const itk::ExceptionObject& e)
  {
    MITK_ERROR << "ITK Exception:" << e.what();
    statisticCalculationSuccessful = false;
  }
  bool statisticChanged = false;

  calculator->SetDoIgnorePixelValue(this->m_IgnoreZeros);
  calculator->SetIgnorePixelValue(0);
  try
  {
    statisticChanged = calculator->ComputeStatistics(m_TimeStep);
  }
  catch ( mitk::Exception& e)
  {
    m_message = e.GetDescription();
    statisticCalculationSuccessful = false;
  }
  catch ( const std::runtime_error &e )
  {
    MITK_ERROR<< "Runtime Exception: " << e.what();
    statisticCalculationSuccessful = false;
  }
  catch ( const std::exception &e )
  {
    MITK_ERROR<< "Standard Exception: " << e.what();
    statisticCalculationSuccessful = false;
  }
  this->m_StatisticChanged = statisticChanged;
  this->m_CalculationSuccessful = statisticCalculationSuccessful;

  if(statisticCalculationSuccessful)
  {
    this->m_StatisticsStruct = calculator->GetStatistics(m_TimeStep);

    if(this->m_TimeStepHistogram.IsNotNull())
    {
      this->m_TimeStepHistogram = NULL;
    }
    this->m_TimeStepHistogram = (HistogramType*) calculator->GetHistogram(m_TimeStep);
  }
}
<commit_msg>Added error message text to the statistics thread for runtime errors and exceptions<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkImageStatisticsCalculationThread.h"

//QT headers
#include <QMessageBox>
#include <QApplication>

QmitkImageStatisticsCalculationThread::QmitkImageStatisticsCalculationThread():QThread(),
  m_StatisticsImage(NULL), m_BinaryMask(NULL), m_PlanarFigureMask(NULL), m_TimeStep(0),
  m_IgnoreZeros(false), m_CalculationSuccessful(false), m_StatisticChanged(false)
{
}

QmitkImageStatisticsCalculationThread::~QmitkImageStatisticsCalculationThread()
{
}

void QmitkImageStatisticsCalculationThread::Initialize( mitk::Image::Pointer image, mitk::Image::Pointer binaryImage, mitk::PlanarFigure::Pointer planarFig )
{
  // reset old values
  if( this->m_StatisticsImage.IsNotNull() )
    this->m_StatisticsImage = 0;

  if( this->m_BinaryMask.IsNotNull() )
    this->m_BinaryMask = 0;

  if( this->m_PlanarFigureMask.IsNotNull())
    this->m_PlanarFigureMask = 0;

  // set new values if passed in
  if(image.IsNotNull())
    this->m_StatisticsImage = image->Clone();
  if(binaryImage.IsNotNull())
    this->m_BinaryMask = binaryImage->Clone();
  if(planarFig.IsNotNull())
    this->m_PlanarFigureMask = dynamic_cast<mitk::PlanarFigure*>(planarFig.GetPointer()); // once clone methods for planar figures are implemented, copy the data here!
}

void QmitkImageStatisticsCalculationThread::SetTimeStep( int times )
{
  this->m_TimeStep = times;
}

int QmitkImageStatisticsCalculationThread::GetTimeStep()
{
  return this->m_TimeStep;
}

mitk::ImageStatisticsCalculator::Statistics QmitkImageStatisticsCalculationThread::GetStatisticsData()
{
  return this->m_StatisticsStruct;
}

mitk::Image::Pointer QmitkImageStatisticsCalculationThread::GetStatisticsImage()
{
  return this->m_StatisticsImage;
}

void QmitkImageStatisticsCalculationThread::SetIgnoreZeroValueVoxel(bool _arg)
{
  this->m_IgnoreZeros = _arg;
}

bool QmitkImageStatisticsCalculationThread::GetIgnoreZeroValueVoxel()
{
  return this->m_IgnoreZeros;
}

std::string QmitkImageStatisticsCalculationThread::GetLastErrorMessage()
{
  return m_message;
}

QmitkImageStatisticsCalculationThread::HistogramType::Pointer
QmitkImageStatisticsCalculationThread::GetTimeStepHistogram()
{
  return this->m_TimeStepHistogram;
}

bool QmitkImageStatisticsCalculationThread::GetStatisticsChangedFlag()
{
  return m_StatisticChanged;
}

bool QmitkImageStatisticsCalculationThread::GetStatisticsUpdateSuccessFlag()
{
  return m_CalculationSuccessful;
}

void QmitkImageStatisticsCalculationThread::run()
{
  bool statisticCalculationSuccessful = true;
  mitk::ImageStatisticsCalculator::Pointer calculator = mitk::ImageStatisticsCalculator::New();

  if(this->m_StatisticsImage.IsNotNull())
  {
    calculator->SetImage(m_StatisticsImage);
    calculator->SetMaskingModeToNone();
  }
  else
  {
    statisticCalculationSuccessful = false;
  }

  // Bug 13416 : The ImageStatistics::SetImageMask() method can throw exceptions, i.e. when the dimensionality
  // of the masked and input image differ, we need to catch them and mark the calculation as failed
  // the same holds for the ::SetPlanarFigure()
  try
  {
    if(this->m_BinaryMask.IsNotNull())
    {

      calculator->SetImageMask(m_BinaryMask);
      calculator->SetMaskingModeToImage();
    }
    if(this->m_PlanarFigureMask.IsNotNull())
    {
      calculator->SetPlanarFigure(m_PlanarFigureMask);
      calculator->SetMaskingModeToPlanarFigure();
    }
  }
  catch( const itk::ExceptionObject& e)
  {
    MITK_ERROR << "ITK Exception:" << e.what();
    statisticCalculationSuccessful = false;
  }
  bool statisticChanged = false;

  calculator->SetDoIgnorePixelValue(this->m_IgnoreZeros);
  calculator->SetIgnorePixelValue(0);
  try
  {
    statisticChanged = calculator->ComputeStatistics(m_TimeStep);
  }
  catch ( mitk::Exception& e)
  {
    m_message = e.GetDescription();
    statisticCalculationSuccessful = false;
  }
  catch ( const std::runtime_error &e )
  {
    m_message = "Exception Occurred. See log for details.";
    MITK_ERROR<< "Runtime Exception: " << e.what();
    statisticCalculationSuccessful = false;
  }
  catch ( const std::exception &e )
  {
    m_message = "Exception Occurred. See log for details.";
    MITK_ERROR<< "Standard Exception: " << e.what();
    statisticCalculationSuccessful = false;
  }
  this->m_StatisticChanged = statisticChanged;
  this->m_CalculationSuccessful = statisticCalculationSuccessful;

  if(statisticCalculationSuccessful)
  {
    this->m_StatisticsStruct = calculator->GetStatistics(m_TimeStep);

    if(this->m_TimeStepHistogram.IsNotNull())
    {
      this->m_TimeStepHistogram = NULL;
    }
    this->m_TimeStepHistogram = (HistogramType*) calculator->GetHistogram(m_TimeStep);
  }
}
<|endoftext|>


<commit_before>// Copyright 2013 Sean McKenna
//
//    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.
//

// object sub-classes (e.g. sphere, plane, triangular mesh OBJ)

// import triangular mesh & BVH storage class
#include "cyCodeBase/cyTriMesh.h"
#include "cyCodeBase/cyBVH.h"

// namespace
using namespace scene;

// Sphere definition
class Sphere: public Object{
  public:

    // constructor
    Sphere(){
      center.Set(0, 0, 0);
      radius = 1.0;
    }

    // intsersect a ray against the unit sphere
    // ray must be transformed into model space, first
    bool intersectRay(Ray &r, HitInfo &h, int face=HIT_FRONT){

      // pre-compute values for quadratic solution
      Point pos = r.pos - center;
      float A = r.dir % r.dir;
      float B = 2.0 * pos % r.dir;
      float C = pos % pos - radius * radius;
      float det = (B * B) - (4 * A * C);

      // if the ray intersects, compute the z-buffer value
      if(det >= 0){
        float z1 = (-B - sqrt(det)) / (2.0 * A);
        float z2 = (-B + sqrt(det)) / (2.0 * A);

        // determine if we have a back hit
        if(z1 * z2 < 0.0)
          h.front = false;

        // if hit is too close, assume it is a back-face hit
        else if(z1 <= getBias())
          h.front = false;

        // check closest z-buffer value, if positive (ahead of our ray)
        if(z1 > getBias()){
          h.z = z1;

          // compute surface intersection and normal
          h.p = r.pos + z1 * r.dir;
          h.n = h.p.GetNormalized();

          // return true, ray is hit
          return true;

        // check the next ray, if necessary
        }else if(z2 > getBias()){
          h.z = z2;

          // compute surface intersection and normal
          h.p = r.pos + z2 * r.dir;
          h.n = h.p.GetNormalized();

          // return true, ray is hit
          return true;

        // otherwise, all z-buffer values are negative, return false
        }else
          return false;
      }

      // otherwise, return false (no ray hit)
      else
        return false;
    }

    // get sphere bounding box
    BoundingBox getBoundBox(){
      return BoundingBox(-1.0, -1.0, -1.0, 1.0, 1.0, 1.0);
    }

  private:

    // sphere center and its radius
    Point center;
    float radius;
};

// Plane definition (a "unit" plane)
class Plane: public Object{
  public:

    // intersect a ray against the "unit" plane
    bool intersectRay(Ray &r, HitInfo &h, int face = HIT_FRONT){

      // only compute for rays not parallel to the unit plane
      if(r.dir.z > getBias() || r.dir.z < getBias()){

        // compute distance along ray direction to plane
        float t = -r.pos.z / r.dir.z;

        // only accept hits in front of ray (with some bias)
        if(t > getBias()){

          // compute the hit point
          Point hit = r.pos + t * r.dir;

          // only allow a hit to occur if on the "unit" plane
          if(hit.x >= -1.0 && hit.y >= -1.0 && hit.x <= 1.0 && hit.y <= 1.0){

            // detect back face hits
            if(r.pos.z < 0.0)
              h.front = false;

            // distance to hit
            h.z = t;

            // set hit point, normal, and return hit info
            h.p = hit;
            h.n = Point(0.0, 0.0, 1.0);
            return true;
          }
        }
      }

      // when no ray hits the "unit" plane
      return false;
    }

    // get plane bounding box
    BoundingBox getBoundBox(){
      return BoundingBox(-1.0, -1.0, 0.0, 1.0, 1.0, 0.0);
    }
};

// Triangular Mesh Object definition (from an OBJ file)
class TriObj: public Object, private cyTriMesh{
  public:

    // intersect a ray against the triangular mesh
    bool intersectRay(Ray &r, HitInfo &h, int face = HIT_FRONT){

      // check our BVH for triangular faces, update hit info
      bool triang = traceBVHNode(r, h, face, bvh.GetRootNodeID());

      // return hit info from intersecting rays in the BVH faces
      return triang;
    }

    // get triangular mesh bounding box
    BoundingBox getBoundBox(){
      return BoundingBox(GetBoundMin(), GetBoundMax());
    }

    // when loading a triangular mesh, get its bounding box
    bool load(const char *file){
      bvh.Clear();
      if(!LoadFromFileObj(file))
        return false;
      if(!HasNormals())
        ComputeNormals();
      ComputeBoundingBox();
      bvh.SetMesh(this,4);
      return true;
    }

  private:

    // add BVH for each triangular mesh
    cyBVHTriMesh bvh;

    // intersect a ray with a single triangle (Moller-Trumbore algorithm)
    bool intersectTriangle(Ray &r, HitInfo &h, int face, int faceID){

      bool mt = false;

      if(mt){

      // grab vertex points
      Point a = V(F(faceID).v[0]);
      Point b = V(F(faceID).v[1]);
      Point c = V(F(faceID).v[2]);

      // compute edge vectors
      Point e1 = b - a;
      Point e2 = c - a;

      // calculate first vector, P
      Point P = r.dir ^ e2;

      // calculate the determinant of the matrix equation
      float determ = e1 % P;

      // only continue for valid determinant ranges
      if(abs(determ) > getBias()){

        // calculate second vector, T
        Point T = r.pos - a;

        // calculate a barycentric component (u)
        float u = T % P;

        // only allow valid barycentric values
        if(u > -getBias() && u < determ * (1.0 + getBias())){

          // calculate a normal of the ray with an edge vector
          Point Q = T ^ e1;

          // calculate a barycentric component (v)
          float v = r.dir % Q;

          // only allow valid barycentric values
          if(v > -getBias() && v + u < determ * (1.0 + getBias())){

            // update barycentric coordinates
            v /= determ;
            u /= determ;

            // compute the barycentric coordinates for interpolating values
            Point bc = Point(1.0 - u - v, u, v);

            // calculate the distance to hit the triangle
            float t = (e2 % Q) / determ;

            // only allow valid distances to hit
            if(t > getBias() && t < h.z){

              // distance to hit
              h.z = t;

              // set hit point, normal
              h.p = GetPoint(faceID, bc);
              h.n = GetNormal(faceID, bc);

              // detect back face hits
              if(determ < 0.0)
                h.front = false;

              // return hit info
              return true;
            }
          }
        }
      }

      // when no ray hits the triangular face
      return false;

      // normal ray tracing
      }else{

      // ignore rays nearly parallel to surface
      Point a = V(F(faceID).v[0]);
      Point b = V(F(faceID).v[1]);
      Point c = V(F(faceID).v[2]);
      Point n = (b - a) ^ (c - a);
      if(r.dir % n > getBias() || r.dir % n < -getBias()){

        // compute distance along ray direction to plane
        Point a = V(F(faceID).v[0]);
        float t = -((r.pos - a) % n) / (r.dir % n);

        // only accept hits in front of ray (with some bias) & closer hits
        if(t > getBias() && t < h.z){

          // compute hit point
          Point hit = r.pos + t * r.dir;

          // simplify problem into 2D by removing the greatest normal component
          Point2 a2;
          Point2 b2;
          Point2 c2;
          Point2 hit2;
          if(abs(n.x) > abs(n.y) && abs(n.x) > abs(n.z)){
            a2 = Point2(a.y, a.z);
            b2 = Point2(b.y, b.z);
            c2 = Point2(c.y, c.z);
            hit2 = Point2(hit.y, hit.z);
          }else if(abs(n.y) > abs(n.x) && abs(n.y) > abs(n.z)){
            a2 = Point2(a.x, a.z);
            b2 = Point2(b.x, b.z);
            c2 = Point2(c.x, c.z);
            hit2 = Point2(hit.x, hit.z);
          }else{
            a2 = Point2(a.x, a.y);
            b2 = Point2(b.x, b.y);
            c2 = Point2(c.x, c.y);
            hit2 = Point2(hit.x, hit.y);
          }

          // compute the area of the triangular face (in 2D)
          float area = (b2 - a2) ^ (c2 - a2);

          // compute smaller areas of the face, relative to the full area, in 2D
          // ensure that we are only calculating positive areas
          // aka, computation of the barycentric coordinates
          float alpha = ((b2 - a2) ^ (hit2 - a2)) / area;
          if(alpha > -getBias() && alpha < 1.0 + getBias()){
            float beta = ((hit2 - a2) ^ (c2 - a2)) / area;
            if(beta > -getBias() && beta < 1.0 + getBias()){
              if(alpha + beta < 1.0 + getBias()){

                // interpolate the normal based on barycentric coordinates
                Point bc = Point(1.0 - alpha - beta, beta, alpha);

                // distance to hit
                h.z = t;

                // set hit point, normal
                h.p = GetPoint(faceID, bc);
                h.n = GetNormal(faceID, bc);

                // detect back face hits
                if(r.dir % h.n > 0.0)
                  h.front = false;

                // return hit info
                return true;
              }
            }
          }
        }
      }

      // when no ray hits the triangular face
      return false;

      }
    }

    // cast a ray into a BVH node, seeing which triangular faces may get hit
    bool traceBVHNode(Ray &r, HitInfo &h, int face, int nodeID){

      // grab node's bounding box
      BoundingBox b = BoundingBox(bvh.GetNodeBounds(nodeID));

      // does ray hit the node bounding box?
      bool hit = b.intersectRay(r, h.z);

      // recurse through child nodes if we hit node
      if(hit){

        // only recursively call function if not at a leaf node
        if(!bvh.IsLeafNode(nodeID)){

          // keep traversing the BVH hierarchy for hits
          int c1 = bvh.GetFirstChildNode(nodeID);
          int c2 = bvh.GetSecondChildNode(nodeID);
          bool hit1 = traceBVHNode(r, h, face, c1);
          bool hit2 = traceBVHNode(r, h, face, c2);

          // if we get no hit
          if(!hit1 && !hit2)
            hit = false;

        // for leaf nodes, trace ray into each triangular face
        }else{

          // get triangular faces of the hit BVH node
          const unsigned int* faces = bvh.GetNodeElements(nodeID);
          int size = bvh.GetNodeElementCount(nodeID);

          // trace the ray into each triangular face, tracking hits
          hit = false;
          for(int i = 0; i < size; i++){
            bool hit1 = intersectTriangle(r, h, face, faces[i]);
            if(!hit && hit1)
              hit = true;
          }
        }
      }

      // return if we hit a face within this node
      return hit;
    }
};
<commit_msg>add in some tweaks to the area-based ray-triangle intersection method, still a few kinks to work out<commit_after>// Copyright 2013 Sean McKenna
//
//    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.
//

// object sub-classes (e.g. sphere, plane, triangular mesh OBJ)

// import triangular mesh & BVH storage class
#include "cyCodeBase/cyTriMesh.h"
#include "cyCodeBase/cyBVH.h"

// namespace
using namespace scene;

// Sphere definition
class Sphere: public Object{
  public:

    // constructor
    Sphere(){
      center.Set(0, 0, 0);
      radius = 1.0;
    }

    // intsersect a ray against the unit sphere
    // ray must be transformed into model space, first
    bool intersectRay(Ray &r, HitInfo &h, int face=HIT_FRONT){

      // pre-compute values for quadratic solution
      Point pos = r.pos - center;
      float A = r.dir % r.dir;
      float B = 2.0 * pos % r.dir;
      float C = pos % pos - radius * radius;
      float det = (B * B) - (4 * A * C);

      // if the ray intersects, compute the z-buffer value
      if(det >= 0){
        float z1 = (-B - sqrt(det)) / (2.0 * A);
        float z2 = (-B + sqrt(det)) / (2.0 * A);

        // determine if we have a back hit
        if(z1 * z2 < 0.0)
          h.front = false;

        // if hit is too close, assume it is a back-face hit
        else if(z1 <= getBias())
          h.front = false;

        // check closest z-buffer value, if positive (ahead of our ray)
        if(z1 > getBias()){
          h.z = z1;

          // compute surface intersection and normal
          h.p = r.pos + z1 * r.dir;
          h.n = h.p.GetNormalized();

          // return true, ray is hit
          return true;

        // check the next ray, if necessary
        }else if(z2 > getBias()){
          h.z = z2;

          // compute surface intersection and normal
          h.p = r.pos + z2 * r.dir;
          h.n = h.p.GetNormalized();

          // return true, ray is hit
          return true;

        // otherwise, all z-buffer values are negative, return false
        }else
          return false;
      }

      // otherwise, return false (no ray hit)
      else
        return false;
    }

    // get sphere bounding box
    BoundingBox getBoundBox(){
      return BoundingBox(-1.0, -1.0, -1.0, 1.0, 1.0, 1.0);
    }

  private:

    // sphere center and its radius
    Point center;
    float radius;
};

// Plane definition (a "unit" plane)
class Plane: public Object{
  public:

    // intersect a ray against the "unit" plane
    bool intersectRay(Ray &r, HitInfo &h, int face = HIT_FRONT){

      // only compute for rays not parallel to the unit plane
      if(r.dir.z > getBias() || r.dir.z < getBias()){

        // compute distance along ray direction to plane
        float t = -r.pos.z / r.dir.z;

        // only accept hits in front of ray (with some bias)
        if(t > getBias()){

          // compute the hit point
          Point hit = r.pos + t * r.dir;

          // only allow a hit to occur if on the "unit" plane
          if(hit.x >= -1.0 && hit.y >= -1.0 && hit.x <= 1.0 && hit.y <= 1.0){

            // detect back face hits
            if(r.pos.z < 0.0)
              h.front = false;

            // distance to hit
            h.z = t;

            // set hit point, normal, and return hit info
            h.p = hit;
            h.n = Point(0.0, 0.0, 1.0);
            return true;
          }
        }
      }

      // when no ray hits the "unit" plane
      return false;
    }

    // get plane bounding box
    BoundingBox getBoundBox(){
      return BoundingBox(-1.0, -1.0, 0.0, 1.0, 1.0, 0.0);
    }
};

// Triangular Mesh Object definition (from an OBJ file)
class TriObj: public Object, private cyTriMesh{
  public:

    // intersect a ray against the triangular mesh
    bool intersectRay(Ray &r, HitInfo &h, int face = HIT_FRONT){

      // check our BVH for triangular faces, update hit info
      bool triang = traceBVHNode(r, h, face, bvh.GetRootNodeID());

      // return hit info from intersecting rays in the BVH faces
      return triang;
    }

    // get triangular mesh bounding box
    BoundingBox getBoundBox(){
      return BoundingBox(GetBoundMin(), GetBoundMax());
    }

    // when loading a triangular mesh, get its bounding box
    bool load(const char *file){
      bvh.Clear();
      if(!LoadFromFileObj(file))
        return false;
      if(!HasNormals())
        ComputeNormals();
      ComputeBoundingBox();
      bvh.SetMesh(this,4);
      return true;
    }

  private:

    // add BVH for each triangular mesh
    cyBVHTriMesh bvh;

    // intersect a ray with a single triangle (Moller-Trumbore algorithm)
    bool intersectTriangle(Ray &r, HitInfo &h, int face, int faceID){

      bool mt = false;

      if(mt){

      // grab vertex points
      Point a = V(F(faceID).v[0]);
      Point b = V(F(faceID).v[1]);
      Point c = V(F(faceID).v[2]);

      // compute edge vectors
      Point e1 = b - a;
      Point e2 = c - a;

      // calculate first vector, P
      Point P = r.dir ^ e2;

      // calculate the determinant of the matrix equation
      float determ = e1 % P;

      // only continue for valid determinant ranges
      if(abs(determ) > getBias()){

        // calculate second vector, T
        Point T = r.pos - a;

        // calculate a barycentric component (u)
        float u = T % P;

        // only allow valid barycentric values
        if(u > -getBias() && u < determ * (1.0 + getBias())){

          // calculate a normal of the ray with an edge vector
          Point Q = T ^ e1;

          // calculate a barycentric component (v)
          float v = r.dir % Q;

          // only allow valid barycentric values
          if(v > -getBias() && v + u < determ * (1.0 + getBias())){

            // update barycentric coordinates
            v /= determ;
            u /= determ;

            // compute the barycentric coordinates for interpolating values
            Point bc = Point(1.0 - u - v, u, v);

            // calculate the distance to hit the triangle
            float t = (e2 % Q) / determ;

            // only allow valid distances to hit
            if(t > getBias() && t < h.z){

              // distance to hit
              h.z = t;

              // set hit point, normal
              h.p = GetPoint(faceID, bc);
              h.n = GetNormal(faceID, bc);

              // detect back face hits
              if(determ < 0.0)
                h.front = false;

              // return hit info
              return true;
            }
          }
        }
      }

      // when no ray hits the triangular face
      return false;

      // normal ray tracing
      }else{

      // grab face vertices and compute face normal
      Point a = V(F(faceID).v[0]);
      Point b = V(F(faceID).v[1]);
      Point c = V(F(faceID).v[2]);
      Point n = (b - a) ^ (c - a);

      // ignore rays nearly parallel to surface
      if(r.dir % n > getBias() || r.dir % n < -getBias()){

        // compute distance along ray direction to plane
        float t = -((r.pos - a) % n) / (r.dir % n);

        // only accept hits in front of ray (with some bias) & closer hits
        if(t > getBias() && t < h.z){

          // compute hit point
          Point hit = r.pos + t * r.dir;

          // simplify problem into 2D by removing the greatest normal component
          Point2 a2;
          Point2 b2;
          Point2 c2;
          Point2 hit2;
          if(abs(n.x) > abs(n.y) && abs(n.x) > abs(n.z)){
            a2 = Point2(a.y, a.z);
            b2 = Point2(b.y, b.z);
            c2 = Point2(c.y, c.z);
            hit2 = Point2(hit.y, hit.z);
          }else if(abs(n.y) > abs(n.x) && abs(n.y) > abs(n.z)){
            a2 = Point2(a.x, a.z);
            b2 = Point2(b.x, b.z);
            c2 = Point2(c.x, c.z);
            hit2 = Point2(hit.x, hit.z);
          }else{
            a2 = Point2(a.x, a.y);
            b2 = Point2(b.x, b.y);
            c2 = Point2(c.x, c.y);
            hit2 = Point2(hit.x, hit.y);
          }

          // compute the area of the triangular face (in 2D)
          float area = (b2 - a2) ^ (c2 - a2);

          // compute smaller areas of the face, relative to the full area, in 2D
          // ensure that we are only calculating positive areas
          // aka, computation of the barycentric coordinates
          float alpha = ((b2 - a2) ^ (hit2 - a2));
          if(alpha > -getBias() && alpha < area * (1.0 + getBias())){
            float beta = ((hit2 - a2) ^ (c2 - a2));
            if(beta > -getBias() && alpha + beta < area * (1.0 + getBias())){

              // scale alpha and beta to the area
              alpha /= area;
              beta /= area;

              // interpolate the normal based on barycentric coordinates
              Point bc = Point(1.0 - alpha - beta, beta, alpha);

              // distance to hit
              h.z = t;

              // set hit point, normal
              h.p = GetPoint(faceID, bc);
              h.n = GetNormal(faceID, bc);

              // detect back face hits
              if(r.dir % h.n > 0.0)
                h.front = false;

              // return hit info
              return true;
            }
          }
        }
      }

      // when no ray hits the triangular face
      return false;
      }
    }

    // cast a ray into a BVH node, seeing which triangular faces may get hit
    bool traceBVHNode(Ray &r, HitInfo &h, int face, int nodeID){

      // grab node's bounding box
      BoundingBox b = BoundingBox(bvh.GetNodeBounds(nodeID));

      // does ray hit the node bounding box?
      bool hit = b.intersectRay(r, h.z);

      // recurse through child nodes if we hit node
      if(hit){

        // only recursively call function if not at a leaf node
        if(!bvh.IsLeafNode(nodeID)){

          // keep traversing the BVH hierarchy for hits
          int c1 = bvh.GetFirstChildNode(nodeID);
          int c2 = bvh.GetSecondChildNode(nodeID);
          bool hit1 = traceBVHNode(r, h, face, c1);
          bool hit2 = traceBVHNode(r, h, face, c2);

          // if we get no hit
          if(!hit1 && !hit2)
            hit = false;

        // for leaf nodes, trace ray into each triangular face
        }else{

          // get triangular faces of the hit BVH node
          const unsigned int* faces = bvh.GetNodeElements(nodeID);
          int size = bvh.GetNodeElementCount(nodeID);

          // trace the ray into each triangular face, tracking hits
          hit = false;
          for(int i = 0; i < size; i++){
            bool hit1 = intersectTriangle(r, h, face, faces[i]);
            if(!hit && hit1)
              hit = true;
          }
        }
      }

      // return if we hit a face within this node
      return hit;
    }
};
<|endoftext|>


<commit_before>//
// Vector/instance_method_mula.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_VECTOR_INSTANCE_METHOD_MULA_HPP
#define EIGENJS_VECTOR_INSTANCE_METHOD_MULA_HPP

namespace EigenJS {

EIGENJS_INSTANCE_METHOD(Vector, mula,
{
  NanScope();

  if (args.Length() == 1) {
    Vector* obj = node::ObjectWrap::Unwrap<Vector>(args.This());
    typename Vector::value_type& value = **obj;

    if (Matrix::is_matrix(args[0])) {
      const Matrix* const& rhs_obj =
        node::ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
      const typename Matrix::value_type& rhs_matrix = **rhs_obj;

      if (T::is_invalid_matrix_product(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      if (rhs_matrix.cols() != 1) {
        NanThrowError("The matrix size must be 1x1");
        NanReturnUndefined();
      }

      value *= rhs_matrix;

      NanReturnValue(args.This());
    } else if (Vector::is_vector(args[0])) {
      const Vector* const& rhs_obj =
        node::ObjectWrap::Unwrap<Vector>(args[0]->ToObject());
      const typename Vector::value_type& rhs_vector = **rhs_obj;

      if (T::is_invalid_matrix_product(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      value *= rhs_vector;

      NanReturnValue(args.This());
    } else if (T::is_scalar(args[0])) {
      value *= args[0]->NumberValue();

      NanReturnValue(args.This());
    }
  }

  EIGENJS_THROW_ERROR_INVALID_ARGUMENT()
  NanReturnUndefined();
})

}  // namespace EigenJS

#endif  // EIGENJS_VECTOR_INSTANCE_METHOD_MULA_HPP
<commit_msg>src: renamed type T<commit_after>//
// Vector/instance_method_mula.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2014 Rick Yang (rick68 at gmail dot com)
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

#ifndef EIGENJS_VECTOR_INSTANCE_METHOD_MULA_HPP
#define EIGENJS_VECTOR_INSTANCE_METHOD_MULA_HPP

namespace EigenJS {

EIGENJS_INSTANCE_METHOD(Vector, mula,
{
  NanScope();

  if (args.Length() == 1) {
    Vector* obj = node::ObjectWrap::Unwrap<Vector>(args.This());
    typename Vector::value_type& value = **obj;

    if (Matrix::is_matrix(args[0])) {
      const Matrix* const& rhs_obj =
        node::ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
      const typename Matrix::value_type& rhs_matrix = **rhs_obj;

      if (Matrix::is_invalid_matrix_product(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      if (rhs_matrix.cols() != 1) {
        NanThrowError("The matrix size must be 1x1");
        NanReturnUndefined();
      }

      value *= rhs_matrix;

      NanReturnValue(args.This());
    } else if (Vector::is_vector(args[0])) {
      const Vector* const& rhs_obj =
        node::ObjectWrap::Unwrap<Vector>(args[0]->ToObject());
      const typename Vector::value_type& rhs_vector = **rhs_obj;

      if (Vector::is_invalid_matrix_product(obj, rhs_obj)) {
        NanReturnUndefined();
      }

      value *= rhs_vector;

      NanReturnValue(args.This());
    } else if (T::is_scalar(args[0])) {
      value *= args[0]->NumberValue();

      NanReturnValue(args.This());
    }
  }

  EIGENJS_THROW_ERROR_INVALID_ARGUMENT()
  NanReturnUndefined();
})

}  // namespace EigenJS

#endif  // EIGENJS_VECTOR_INSTANCE_METHOD_MULA_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2012-2013, the scalloc Project Authors.  All rights reserved.
// Please see the AUTHORS file for details.  Use of this source code is governed
// by a BSD license that can be found in the LICENSE file.

#include "slab_sc_allocator.h"

#include "allocators/page_heap.h"
#include "log.h"
#include "runtime_vars.h"

namespace scalloc {

void SlabScAllocator::InitModule() {
  PageHeap::InitModule();
}

void SlabScAllocator::Init(const uint64_t id) {
  id_ = id;
  ActiveOwner dummy;
  dummy.Reset(true, id_);
  me_active_ = dummy.raw;
  dummy.Reset(false, id_);
  me_inactive_ = dummy.raw;
}

void* SlabScAllocator::AllocateNoSlab(const size_t sc, const size_t size) {
  // Size class 0 represents an object of size 0, which results in malloc()
  // returning NULL.
  if (sc == 0) {
    return NULL;
  }

  if (my_headers_[sc] != NULL) {
#ifdef PROFILER_ON
    Profiler::GetProfiler().LogAllocation(size);
#endif //PROFILER_ON
    // Only try to steal we had a slab at least once.
    SlabHeader* hdr;
    void* p = DQScAllocator::Instance().Allocate(sc, id_, id_, &hdr);
    if (p != NULL) {
#ifdef PROFILER_ON
      Profiler::GetProfiler().LogBlockStealing();
#endif //PROFILER_ON
      if (hdr != NULL) {
        SetActiveSlab(sc, hdr);
      } else {
#ifdef GLOBAL_CLEANUP
        if (reinterpret_cast<SlabHeader*>(BlockHeader::GetFromObject(p))->aowner.owner != id_) {
          Refill(sc);
        }
#endif  // GLOBAL_CLEANUP
      }
      return p;
    }
  }

  Refill(sc);
  return Allocate(size);
}

void SlabScAllocator::Refill(const size_t sc) {
#ifdef PROFILER_ON
  Profiler::GetProfiler().LogSizeclassRefill();
#endif //PROFILER_ON
  LOG(kTrace, "[SlabAllocator]: refilling size class: %lu", sc);
  uintptr_t block = reinterpret_cast<uintptr_t>(PageHeap::GetHeap()->Get());
  if (block == 0) {
    ErrorOut("PageHeap out of memory");
  }
  SlabHeader* hdr = InitSlab(block,
                             kPageMultiple * RuntimeVars::SystemPageSize(),
                             sc);
  SetActiveSlab(sc, hdr);
}

SlabHeader* SlabScAllocator::InitSlab(uintptr_t block,
                                      size_t len,
                                      const size_t sc) {
  const size_t obj_size = SizeMap::Instance().ClassToSize(sc);
  size_t sys_page_size = RuntimeVars::SystemPageSize();
  SlabHeader* main_hdr = reinterpret_cast<SlabHeader*>(block);
  main_hdr->Reset(sc, id_);
  main_hdr->aowner.owner = id_;
  main_hdr->aowner.active = true;

  // We need to initialize the flist and place ForwardHeaders every system page
  // size bytes, since this is where we search for headers (for small AND large
  // objects)

  size_t nr_objects;

  // First block is special, since it contains the full slab header, while
  // others only contain the forward header to the first block.
  nr_objects = (sys_page_size - sizeof(*main_hdr)) / obj_size;
  main_hdr->flist.FromBlock(reinterpret_cast<void*>(block + sizeof(*main_hdr)),
                            obj_size,
                            nr_objects);
  len -= sys_page_size;
  block += sys_page_size;

  // Fill with forward headers and flist objects.
  for (; len >= sys_page_size; len -= sys_page_size) {
    ForwardHeader* fwd_hdr = reinterpret_cast<ForwardHeader*>(block);
    fwd_hdr->Reset(main_hdr);
    nr_objects = (sys_page_size - sizeof(*fwd_hdr)) / obj_size;
    main_hdr->flist.AddRange(reinterpret_cast<void*>(block + sizeof(*fwd_hdr)),
                             obj_size,
                             nr_objects);
    block += sys_page_size;
  }

  return main_hdr;
}

void SlabScAllocator::Destroy() {
  // Destroying basically means giving up all active spans.  We can only give up
  // our current spans, since we do not have references to the others.  Assuming
  // the mutator had no memory leak (i.e. all non-shared objects have been
  // freed), a span now can stay active forever (all reusable blocks travel
  // through the remote freelists), or it is already inactive (and thus
  // available for reuse).
  for (size_t i = 0; i < kNumClasses; i++) {
    if (my_headers_[i]) {
      my_headers_[i]->aowner.active = false;
    }
  }
}

}  // namespace scalloc
<commit_msg>Linted.<commit_after>// Copyright (c) 2012-2013, the scalloc Project Authors.  All rights reserved.
// Please see the AUTHORS file for details.  Use of this source code is governed
// by a BSD license that can be found in the LICENSE file.

#include "slab_sc_allocator.h"

#include "allocators/page_heap.h"
#include "log.h"
#include "runtime_vars.h"

namespace scalloc {

void SlabScAllocator::InitModule() {
  PageHeap::InitModule();
}

void SlabScAllocator::Init(const uint64_t id) {
  id_ = id;
  ActiveOwner dummy;
  dummy.Reset(true, id_);
  me_active_ = dummy.raw;
  dummy.Reset(false, id_);
  me_inactive_ = dummy.raw;
}

void* SlabScAllocator::AllocateNoSlab(const size_t sc, const size_t size) {
  // Size class 0 represents an object of size 0, which results in malloc()
  // returning NULL.
  if (sc == 0) {
    return NULL;
  }

  if (my_headers_[sc] != NULL) {
#ifdef PROFILER_ON
    Profiler::GetProfiler().LogAllocation(size);
#endif  // PROFILER_ON
    // Only try to steal we had a slab at least once.
    SlabHeader* hdr;
    void* p = DQScAllocator::Instance().Allocate(sc, id_, id_, &hdr);
    if (p != NULL) {
#ifdef PROFILER_ON
      Profiler::GetProfiler().LogBlockStealing();
#endif  // PROFILER_ON
      if (hdr != NULL) {
        SetActiveSlab(sc, hdr);
      } else {
#ifdef GLOBAL_CLEANUP
        if (reinterpret_cast<SlabHeader*>(BlockHeader::GetFromObject(p))->aowner.owner != id_) {
          Refill(sc);
        }
#endif  // GLOBAL_CLEANUP
      }
      return p;
    }
  }

  Refill(sc);
  return Allocate(size);
}

void SlabScAllocator::Refill(const size_t sc) {
#ifdef PROFILER_ON
  Profiler::GetProfiler().LogSizeclassRefill();
#endif  // PROFILER_ON
  LOG(kTrace, "[SlabAllocator]: refilling size class: %lu", sc);
  uintptr_t block = reinterpret_cast<uintptr_t>(PageHeap::GetHeap()->Get());
  if (block == 0) {
    ErrorOut("PageHeap out of memory");
  }
  SlabHeader* hdr = InitSlab(block,
                             kPageMultiple * RuntimeVars::SystemPageSize(),
                             sc);
  SetActiveSlab(sc, hdr);
}

SlabHeader* SlabScAllocator::InitSlab(uintptr_t block,
                                      size_t len,
                                      const size_t sc) {
  const size_t obj_size = SizeMap::Instance().ClassToSize(sc);
  size_t sys_page_size = RuntimeVars::SystemPageSize();
  SlabHeader* main_hdr = reinterpret_cast<SlabHeader*>(block);
  main_hdr->Reset(sc, id_);
  main_hdr->aowner.owner = id_;
  main_hdr->aowner.active = true;

  // We need to initialize the flist and place ForwardHeaders every system page
  // size bytes, since this is where we search for headers (for small AND large
  // objects)

  size_t nr_objects;

  // First block is special, since it contains the full slab header, while
  // others only contain the forward header to the first block.
  nr_objects = (sys_page_size - sizeof(*main_hdr)) / obj_size;
  main_hdr->flist.FromBlock(reinterpret_cast<void*>(block + sizeof(*main_hdr)),
                            obj_size,
                            nr_objects);
  len -= sys_page_size;
  block += sys_page_size;

  // Fill with forward headers and flist objects.
  for (; len >= sys_page_size; len -= sys_page_size) {
    ForwardHeader* fwd_hdr = reinterpret_cast<ForwardHeader*>(block);
    fwd_hdr->Reset(main_hdr);
    nr_objects = (sys_page_size - sizeof(*fwd_hdr)) / obj_size;
    main_hdr->flist.AddRange(reinterpret_cast<void*>(block + sizeof(*fwd_hdr)),
                             obj_size,
                             nr_objects);
    block += sys_page_size;
  }

  return main_hdr;
}

void SlabScAllocator::Destroy() {
  // Destroying basically means giving up all active spans.  We can only give up
  // our current spans, since we do not have references to the others.  Assuming
  // the mutator had no memory leak (i.e. all non-shared objects have been
  // freed), a span now can stay active forever (all reusable blocks travel
  // through the remote freelists), or it is already inactive (and thus
  // available for reuse).
  for (size_t i = 0; i < kNumClasses; i++) {
    if (my_headers_[i]) {
      my_headers_[i]->aowner.active = false;
    }
  }
}

}  // namespace scalloc
<|endoftext|>