<commit_before>#include <QSettings>
#include <QFile>
#include <QNetworkCookie>
#include <iostream>
#include <QSet>
#include "page.h"
#include "json.h"
#include "math.h"
#include "site.h"

Page::Page(Profile *profile, Site *site, QList<Site*> sites, QStringList tags, int page, int limit, QStringList postFiltering, bool smart, QObject *parent, int pool, int lastPage, int lastPageMinId, int lastPageMaxId)
	: QObject(parent), m_site(site), m_regexApi(0), m_postFiltering(postFiltering), m_errors(QStringList()), m_imagesPerPage(limit), m_currentSource(0), m_lastPage(lastPage), m_lastPageMinId(lastPageMinId), m_lastPageMaxId(lastPageMaxId), m_smart(smart)
{
	m_website = m_site->url();
	m_imagesCount = -1;
	m_pagesCount = -1;

	// Replace shortcuts to increase compatibility
	QString text = " "+tags.join(" ")+" ";
	text.replace(" rating:s ", " rating:safe ", Qt::CaseInsensitive)
		.replace(" rating:q ", " rating:questionable ", Qt::CaseInsensitive)
		.replace(" rating:e ", " rating:explicit ", Qt::CaseInsensitive)
		.replace(" -rating:s ", " -rating:safe ", Qt::CaseInsensitive)
		.replace(" -rating:q ", " -rating:questionable ", Qt::CaseInsensitive)
		.replace(" -rating:e ", " -rating:explicit ", Qt::CaseInsensitive);
	tags = text.split(" ", QString::SkipEmptyParts);
	tags.removeDuplicates();

	// Get the list of all enabled modifiers
	QStringList modifiers = QStringList();
	for (Site *site : sites)
	{
		if (site->contains("Modifiers"))
		{ modifiers.append(site->value("Modifiers").trimmed().split(" ", QString::SkipEmptyParts)); }
	}
	if (m_site->contains("Modifiers"))
	{
		QStringList mods = m_site->value("Modifiers").trimmed().split(" ", QString::SkipEmptyParts);
		for (int j = 0; j < mods.size(); j++)
		{ modifiers.removeAll(mods[j]); }
	}

	// Remove modifiers from tags
	for (int k = 0; k < modifiers.size(); k++)
	{ tags.removeAll(modifiers[k]); }
	m_search = tags;

	// Generate pages
	for (Api *api : m_site->getApis())
	{
		m_pageApis.append(new PageApi(this, profile, m_site, api, m_search, page, limit, postFiltering, smart, parent, pool, lastPage, lastPageMinId, lastPageMaxId));
		if (api->getName() == "Html" && m_regexApi < 0)
		{ m_regexApi = m_pageApis.count() - 1; }
	}
	m_currentApi = -1;

	// Set values
	m_page = page;
	m_pool = pool;
	fallback(false);
}
Page::~Page()
{
	qDeleteAll(m_pageApis);
}

void Page::fallback(bool bload)
{
	if (m_currentApi >= m_site->getApis().count() - 1)
	{
		log(tr("Aucune source valide du site n'a retourné de résultat."));
		m_errors.append(tr("Aucune source valide du site n'a retourné de résultat."));
		emit failedLoading(this);
		return;
	}

	m_currentApi++;
	if (m_currentApi > 0)
		log(tr("Chargement en %1 échoué. Nouvel essai en %2.").arg(m_site->getApis().at(m_currentApi - 1)->getName()).arg(m_site->getApis().at(m_currentApi)->getName()));

	if (bload)
		load();
}

void Page::setLastPage(Page *page)
{
	m_lastPage = page->page();
	m_lastPageMaxId = page->maxId();
	m_lastPageMinId = page->minId();

	for (PageApi *api : m_pageApis)
		api->setLastPage(page);

	m_currentApi--;
	if (!page->nextPage().isEmpty())
	{ /*m_url = page->nextPage();*/ }
	else
	{ fallback(false); }
}

void Page::load(bool rateLimit)
{
	connect(m_pageApis[m_currentApi], &PageApi::finishedLoading, this, &Page::loadFinished);
	m_pageApis[m_currentApi]->load(rateLimit);
}
void Page::loadFinished(PageApi *api, PageApi::LoadResult status)
{
	if (api != m_pageApis[m_currentApi])
		return;

	if (status == PageApi::LoadResult::Ok)
		emit finishedLoading(this);
	else
		fallback();
}
void Page::abort()
{
	m_pageApis[m_currentApi]->abort();
}

void Page::loadTags()
{
	if (m_regexApi < 0)
		return;

	connect(m_pageApis[m_regexApi], &PageApi::finishedLoadingTags, this, &Page::loadTagsFinished);
	m_pageApis[m_regexApi]->loadTags();
}
void Page::loadTagsFinished(PageApi *api)
{
	if (m_regexApi < 0 || api != m_pageApis[m_regexApi])
		return;

	emit finishedLoadingTags(this);
}
void Page::abortTags()
{
	if (m_regexApi < 0)
		return;

	m_pageApis[m_regexApi]->abortTags();
}

void Page::clear()
{
	for (PageApi *pageApi : m_pageApis)
		pageApi->clear();
}

Site			*Page::site()		{ return m_site;								}
QString			Page::website()		{ return m_website;								}
QString			Page::wiki()		{ return m_wiki;								}
QStringList		Page::search()		{ return m_search;								}
QStringList		Page::errors()		{ return m_errors;								}
int				Page::imagesPerPage()	{ return m_imagesPerPage;					}
int				Page::page()		{ return m_page;								}
QList<QSharedPointer<Image>>	Page::images()		{ return m_pageApis[m_currentApi]->images();	}
QUrl			Page::url()			{ return m_pageApis[m_currentApi]->url();		}
QString			Page::source()		{ return m_pageApis[m_currentApi]->source();	}
QList<Tag>		Page::tags()		{ return m_pageApis[m_currentApi]->tags();		}
QUrl			Page::nextPage()	{ return m_pageApis[m_currentApi]->nextPage();	}
QUrl			Page::prevPage()	{ return m_pageApis[m_currentApi]->prevPage();	}
int				Page::highLimit()	{ return m_pageApis[m_currentApi]->highLimit(); }

int Page::imagesCount(bool guess)
{
	if (m_regexApi >= 0)
	{
		int count = m_pageApis[m_regexApi]->imagesCount(false);
		if (count >= 0)
			return count;
	}
	return m_pageApis[m_currentApi]->imagesCount(guess);
}
int Page::pagesCount(bool guess)
{
	if (m_regexApi >= 0)
	{
		int count = m_pageApis[m_regexApi]->pagesCount(false);
		if (count >= 0)
			return count;
	}
	return m_pageApis[m_currentApi]->pagesCount(guess);
}

int Page::maxId()
{
	return m_pageApis[m_currentApi]->maxId();
}
int Page::minId()
{
	return m_pageApis[m_currentApi]->minId();
}
<commit_msg>English in Page<commit_after>#include <QSettings>
#include <QFile>
#include <QNetworkCookie>
#include <iostream>
#include <QSet>
#include "page.h"
#include "json.h"
#include "math.h"
#include "site.h"

Page::Page(Profile *profile, Site *site, QList<Site*> sites, QStringList tags, int page, int limit, QStringList postFiltering, bool smart, QObject *parent, int pool, int lastPage, int lastPageMinId, int lastPageMaxId)
	: QObject(parent), m_site(site), m_regexApi(0), m_postFiltering(postFiltering), m_errors(QStringList()), m_imagesPerPage(limit), m_currentSource(0), m_lastPage(lastPage), m_lastPageMinId(lastPageMinId), m_lastPageMaxId(lastPageMaxId), m_smart(smart)
{
	m_website = m_site->url();
	m_imagesCount = -1;
	m_pagesCount = -1;

	// Replace shortcuts to increase compatibility
	QString text = " "+tags.join(" ")+" ";
	text.replace(" rating:s ", " rating:safe ", Qt::CaseInsensitive)
		.replace(" rating:q ", " rating:questionable ", Qt::CaseInsensitive)
		.replace(" rating:e ", " rating:explicit ", Qt::CaseInsensitive)
		.replace(" -rating:s ", " -rating:safe ", Qt::CaseInsensitive)
		.replace(" -rating:q ", " -rating:questionable ", Qt::CaseInsensitive)
		.replace(" -rating:e ", " -rating:explicit ", Qt::CaseInsensitive);
	tags = text.split(" ", QString::SkipEmptyParts);
	tags.removeDuplicates();

	// Get the list of all enabled modifiers
	QStringList modifiers = QStringList();
	for (Site *site : sites)
	{
		if (site->contains("Modifiers"))
		{ modifiers.append(site->value("Modifiers").trimmed().split(" ", QString::SkipEmptyParts)); }
	}
	if (m_site->contains("Modifiers"))
	{
		QStringList mods = m_site->value("Modifiers").trimmed().split(" ", QString::SkipEmptyParts);
		for (int j = 0; j < mods.size(); j++)
		{ modifiers.removeAll(mods[j]); }
	}

	// Remove modifiers from tags
	for (int k = 0; k < modifiers.size(); k++)
	{ tags.removeAll(modifiers[k]); }
	m_search = tags;

	// Generate pages
	for (Api *api : m_site->getApis())
	{
		m_pageApis.append(new PageApi(this, profile, m_site, api, m_search, page, limit, postFiltering, smart, parent, pool, lastPage, lastPageMinId, lastPageMaxId));
		if (api->getName() == "Html" && m_regexApi < 0)
		{ m_regexApi = m_pageApis.count() - 1; }
	}
	m_currentApi = -1;

	// Set values
	m_page = page;
	m_pool = pool;
	fallback(false);
}
Page::~Page()
{
	qDeleteAll(m_pageApis);
}

void Page::fallback(bool bload)
{
	if (m_currentApi >= m_site->getApis().count() - 1)
	{
		QString msg = tr("No valid source of the site returned result.");
		log(msg);
		m_errors.append(msg);
		emit failedLoading(this);
		return;
	}

	m_currentApi++;
	if (m_currentApi > 0)
		log(tr("Loading using %1 failed. Retry using %2.").arg(m_site->getApis().at(m_currentApi - 1)->getName()).arg(m_site->getApis().at(m_currentApi)->getName()));

	if (bload)
		load();
}

void Page::setLastPage(Page *page)
{
	m_lastPage = page->page();
	m_lastPageMaxId = page->maxId();
	m_lastPageMinId = page->minId();

	for (PageApi *api : m_pageApis)
		api->setLastPage(page);

	m_currentApi--;
	if (!page->nextPage().isEmpty())
	{ /*m_url = page->nextPage();*/ }
	else
	{ fallback(false); }
}

void Page::load(bool rateLimit)
{
	connect(m_pageApis[m_currentApi], &PageApi::finishedLoading, this, &Page::loadFinished);
	m_pageApis[m_currentApi]->load(rateLimit);
}
void Page::loadFinished(PageApi *api, PageApi::LoadResult status)
{
	if (api != m_pageApis[m_currentApi])
		return;

	if (status == PageApi::LoadResult::Ok)
		emit finishedLoading(this);
	else
		fallback();
}
void Page::abort()
{
	m_pageApis[m_currentApi]->abort();
}

void Page::loadTags()
{
	if (m_regexApi < 0)
		return;

	connect(m_pageApis[m_regexApi], &PageApi::finishedLoadingTags, this, &Page::loadTagsFinished);
	m_pageApis[m_regexApi]->loadTags();
}
void Page::loadTagsFinished(PageApi *api)
{
	if (m_regexApi < 0 || api != m_pageApis[m_regexApi])
		return;

	emit finishedLoadingTags(this);
}
void Page::abortTags()
{
	if (m_regexApi < 0)
		return;

	m_pageApis[m_regexApi]->abortTags();
}

void Page::clear()
{
	for (PageApi *pageApi : m_pageApis)
		pageApi->clear();
}

Site			*Page::site()		{ return m_site;								}
QString			Page::website()		{ return m_website;								}
QString			Page::wiki()		{ return m_wiki;								}
QStringList		Page::search()		{ return m_search;								}
QStringList		Page::errors()		{ return m_errors;								}
int				Page::imagesPerPage()	{ return m_imagesPerPage;					}
int				Page::page()		{ return m_page;								}
QList<QSharedPointer<Image>>	Page::images()		{ return m_pageApis[m_currentApi]->images();	}
QUrl			Page::url()			{ return m_pageApis[m_currentApi]->url();		}
QString			Page::source()		{ return m_pageApis[m_currentApi]->source();	}
QList<Tag>		Page::tags()		{ return m_pageApis[m_currentApi]->tags();		}
QUrl			Page::nextPage()	{ return m_pageApis[m_currentApi]->nextPage();	}
QUrl			Page::prevPage()	{ return m_pageApis[m_currentApi]->prevPage();	}
int				Page::highLimit()	{ return m_pageApis[m_currentApi]->highLimit(); }

int Page::imagesCount(bool guess)
{
	if (m_regexApi >= 0)
	{
		int count = m_pageApis[m_regexApi]->imagesCount(false);
		if (count >= 0)
			return count;
	}
	return m_pageApis[m_currentApi]->imagesCount(guess);
}
int Page::pagesCount(bool guess)
{
	if (m_regexApi >= 0)
	{
		int count = m_pageApis[m_regexApi]->pagesCount(false);
		if (count >= 0)
			return count;
	}
	return m_pageApis[m_currentApi]->pagesCount(guess);
}

int Page::maxId()
{
	return m_pageApis[m_currentApi]->maxId();
}
int Page::minId()
{
	return m_pageApis[m_currentApi]->minId();
}
<|endoftext|>


<commit_before>#include "common.hpp"

extern "C"
long syscall_SYS_mremap() {
  STUB("mremap");
  return 0;
}
<commit_msg>mremap: Be honest about not being implemented<commit_after>#include "common.hpp"

extern "C"
long syscall_SYS_mremap() {
  STUB("mremap");
  return -ENOSYS;
}
<|endoftext|>


<commit_before>/*
 * LClient.cpp
 *
 *  Created on: Apr 28, 2015
 *      Author: luodichen
 */

#include "../common/errcode.h"
#include "LClient.h"
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>

static const int MAX_TIMEOUT = 8;
static const int MAX_RETRY = 10;

LClient::LClient(in_addr_t address, uint16_t port, TYPE type, uint32_t timeout)
    : INetIO()
    , m_address()
    , m_sPort(port)
    , m_nTimeout(timeout)
    , m_type(type)
    , m_socket(-1)
    , m_connected(false)
    , m_sockaddr()
{
    m_address.s_addr = address;
    assert(0 == Init());
}

LClient::LClient(const char *szAddress, uint16_t port, TYPE type, uint32_t timeout)
    : INetIO()
    , m_address()
    , m_sPort(port)
    , m_nTimeout(timeout)
    , m_type(type)
    , m_socket(-1)
    , m_connected(false)
    , m_sockaddr()
{
    m_address.s_addr = inet_addr(szAddress);
    assert(0 == Init());
}

LClient::~LClient()
{

}

int LClient::Init()
{
    int ret = 0;
    int type = (LClient::TCP == m_type) ? SOCK_STREAM : SOCK_DGRAM;
    int protocol = (LClient::TCP == m_type) ? IPPROTO_TCP : IPPROTO_UDP;
    m_socket = socket(AF_INET, type, protocol);
    if (-1 == m_socket)
        ret = -1;

    if (LClient::TCP == m_type)
    {
        struct timeval timeout;
        memset((void *)&timeout, 0, sizeof(timeout));
        timeout.tv_sec = m_nTimeout;

        setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (void *)&timeout, sizeof(timeout));
        setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, sizeof(timeout));
    }

    memset((void *)&m_sockaddr, 0, sizeof(m_sockaddr));
    m_sockaddr.sin_family = AF_INET;
    m_sockaddr.sin_port = htons(m_sPort);
    m_sockaddr.sin_addr = m_address;

    return ret;
}

int LClient::Write(const uint8_t *pBuffer, size_t size)
{
    if (!m_connected
            && 0 != connect(m_socket, (sockaddr*)&m_sockaddr, sizeof(m_sockaddr)))
    {
        return ERR::SOCKET_CONNECT_FAILED;
    }
    m_connected = true;

    if (-1 == send(m_socket, pBuffer, size, 0))
    {
        return ERR::SEND_DATA_FAILED;
    }

    return 0;
}

int LClient::Read(uint8_t *pBuffer, size_t max)
{
    int ret = 0;
    if (!m_connected)
        return ERR::NOT_CONNECTED;

    if (LClient::TCP == m_type)
    {
        int count = read(m_socket, (void *)pBuffer, max);
        if (-1 == count)
        {
            ret = ERR::RECV_FAILED;
        }
        ret = count;
    }
    else
    {
        struct timeval timeout;
        memset((void *)&timeout, 0, sizeof(timeout));
        timeout.tv_sec = 1;
        time_t tBegin = time(NULL);

        int count = 0;
        int nTryCount = 0;
        ret = ERR::RECV_TIMEOUT;
        while ((time(NULL) - tBegin < m_nTimeout) && nTryCount++ < MAX_TIMEOUT)
        {
            setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, sizeof(timeout));
            count = read(m_socket, (void *)pBuffer, max);

            if (-1 == count)
            {
                timeout.tv_sec = ((timeout.tv_sec * 2 <= MAX_TIMEOUT) ? 2 : 1) * timeout.tv_sec;
            }
            else if (count >= 0)
            {
                ret = count;
                break;
            }
            else
            {
                ret = ERR::RECV_FAILED;
                break;
            }
        }
    }
    return ret;
}
<commit_msg>HEY YOU FORGOT TO CLOSE THE SOCKETS!!!<commit_after>/*
 * LClient.cpp
 *
 *  Created on: Apr 28, 2015
 *      Author: luodichen
 */

#include "../common/errcode.h"
#include "LClient.h"
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>

static const int MAX_TIMEOUT = 8;
static const int MAX_RETRY = 10;

LClient::LClient(in_addr_t address, uint16_t port, TYPE type, uint32_t timeout)
    : INetIO()
    , m_address()
    , m_sPort(port)
    , m_nTimeout(timeout)
    , m_type(type)
    , m_socket(-1)
    , m_connected(false)
    , m_sockaddr()
{
    m_address.s_addr = address;
    assert(0 == Init());
}

LClient::LClient(const char *szAddress, uint16_t port, TYPE type, uint32_t timeout)
    : INetIO()
    , m_address()
    , m_sPort(port)
    , m_nTimeout(timeout)
    , m_type(type)
    , m_socket(-1)
    , m_connected(false)
    , m_sockaddr()
{
    m_address.s_addr = inet_addr(szAddress);
    assert(0 == Init());
}

LClient::~LClient()
{
    if (m_socket >= 0)
    {
        close(m_socket);
        m_socket = -1;
    }
}

int LClient::Init()
{
    int ret = 0;
    int type = (LClient::TCP == m_type) ? SOCK_STREAM : SOCK_DGRAM;
    int protocol = (LClient::TCP == m_type) ? IPPROTO_TCP : IPPROTO_UDP;
    m_socket = socket(AF_INET, type, protocol);
    if (-1 == m_socket)
        ret = -1;

    if (LClient::TCP == m_type)
    {
        struct timeval timeout;
        memset((void *)&timeout, 0, sizeof(timeout));
        timeout.tv_sec = m_nTimeout;

        setsockopt(m_socket, SOL_SOCKET, SO_SNDTIMEO, (void *)&timeout, sizeof(timeout));
        setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, sizeof(timeout));
    }

    memset((void *)&m_sockaddr, 0, sizeof(m_sockaddr));
    m_sockaddr.sin_family = AF_INET;
    m_sockaddr.sin_port = htons(m_sPort);
    m_sockaddr.sin_addr = m_address;

    return ret;
}

int LClient::Write(const uint8_t *pBuffer, size_t size)
{
    if (!m_connected
            && 0 != connect(m_socket, (sockaddr*)&m_sockaddr, sizeof(m_sockaddr)))
    {
        return ERR::SOCKET_CONNECT_FAILED;
    }
    m_connected = true;

    if (-1 == send(m_socket, pBuffer, size, 0))
    {
        return ERR::SEND_DATA_FAILED;
    }

    return 0;
}

int LClient::Read(uint8_t *pBuffer, size_t max)
{
    int ret = 0;
    if (!m_connected)
        return ERR::NOT_CONNECTED;

    if (LClient::TCP == m_type)
    {
        int count = read(m_socket, (void *)pBuffer, max);
        if (-1 == count)
        {
            ret = ERR::RECV_FAILED;
        }
        ret = count;
    }
    else
    {
        struct timeval timeout;
        memset((void *)&timeout, 0, sizeof(timeout));
        timeout.tv_sec = 1;
        time_t tBegin = time(NULL);

        int count = 0;
        int nTryCount = 0;
        ret = ERR::RECV_TIMEOUT;
        while ((time(NULL) - tBegin < m_nTimeout) && nTryCount++ < MAX_TIMEOUT)
        {
            setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout, sizeof(timeout));
            count = read(m_socket, (void *)pBuffer, max);

            if (-1 == count)
            {
                timeout.tv_sec = ((timeout.tv_sec * 2 <= MAX_TIMEOUT) ? 2 : 1) * timeout.tv_sec;
            }
            else if (count >= 0)
            {
                ret = count;
                break;
            }
            else
            {
                ret = ERR::RECV_FAILED;
                break;
            }
        }
    }
    return ret;
}
<|endoftext|>


<commit_before>// v8
#include <v8.h>

// node
#include <node.h>
#include <node_version.h>
#include "mapnik3x_compatibility.hpp"

// node-mapnik
#include "mapnik_vector_tile.hpp"
#include "mapnik_map.hpp"
#include "mapnik_color.hpp"
#include "mapnik_geometry.hpp"
#include "mapnik_feature.hpp"
#include "mapnik_fonts.hpp"
#include "mapnik_plugins.hpp"
#include "mapnik_palette.hpp"
#include "mapnik_projection.hpp"
#include "mapnik_layer.hpp"
#include "mapnik_datasource.hpp"
#include "mapnik_featureset.hpp"
#include "mapnik_memory_datasource.hpp"
#include "mapnik_image.hpp"
#include "mapnik_image_view.hpp"
#include "mapnik_grid.hpp"
#include "mapnik_cairo_surface.hpp"
#include "mapnik_grid_view.hpp"
#ifdef NODE_MAPNIK_EXPRESSION
#include "mapnik_expression.hpp"
#endif
#include "utils.hpp"

#include <libxml/parser.h>
#include <libxml/xmlversion.h>

#include <gdal_priv.h>
#include <ogr_api.h>

// mapnik
#include <mapnik/config.hpp> // for MAPNIK_DECL
#include <mapnik/version.hpp>
#if MAPNIK_VERSION >= 200100
#include <mapnik/marker_cache.hpp>
#include <mapnik/mapped_memory_cache.hpp>
#include <mapnik/image_compositing.hpp>
#endif

// boost
#include <boost/version.hpp>

// cairo
#if defined(HAVE_CAIRO)
#include <cairo.h>
#endif

namespace node_mapnik {

using namespace node;
using namespace v8;

/**
 * Optional notification that the embedder is idle.
 * V8 uses the notification to reduce memory footprint.
 * This call can be used repeatedly if the embedder remains idle.
 * Returns true if the embedder should stop calling IdleNotification
 * until real work has been done.  This indicates that V8 has done
 * as much cleanup as it will be able to do.
 */
static Handle<Value> gc(const Arguments& args)
{
    HandleScope scope;
    return scope.Close(Boolean::New(V8::IdleNotification()));
}

static std::string format_version(int version)
{
    std::ostringstream s;
    s << version/100000 << "." << version/100 % 1000  << "." << version % 100;
    return s.str();
}

static Handle<Value> clearCache(const Arguments& args)
{
    HandleScope scope;
#if MAPNIK_VERSION >= 200300
    #if defined(SHAPE_MEMORY_MAPPED_FILE)
        mapnik::marker_cache::instance().clear();
        mapnik::mapped_memory_cache::instance().clear();
    #endif
#else
    #if MAPNIK_VERSION >= 200200
        mapnik::marker_cache::instance().clear();
        mapnik::mapped_memory_cache::instance().clear();
    #else
        #if MAPNIK_VERSION >= 200100
            mapnik::marker_cache::instance()->clear();
            mapnik::mapped_memory_cache::instance()->clear();
        #endif
    #endif
#endif
    return scope.Close(Undefined());
}

static Handle<Value> shutdown(const Arguments& args)
{
    HandleScope scope;
    google::protobuf::ShutdownProtobufLibrary();
    // http://lists.fedoraproject.org/pipermail/devel/2010-January/129117.html
    xmlCleanupParser();
    GDALDestroyDriverManager();
    OGRCleanupAll();
    return scope.Close(Undefined());
}

extern "C" {

    static void InitMapnik (Handle<Object> target)
    {
        HandleScope scope;
        GOOGLE_PROTOBUF_VERIFY_VERSION;
        // https://mail.gnome.org/archives/xml/2007-October/msg00004.html
        // calls http://xmlsoft.org/html/libxml-xmlversion.html#xmlCheckVersion
        // which internall calls http://xmlsoft.org/html/libxml-parser.html#xmlInitParser
        // see 'parserInternals.c' for details / requires xmlCleanupParser(); at exit
        LIBXML_TEST_VERSION;

        // module level functions
        NODE_SET_METHOD(target, "register_datasource", node_mapnik::register_datasource);
        NODE_SET_METHOD(target, "register_datasources", node_mapnik::register_datasources);
        NODE_SET_METHOD(target, "datasources", node_mapnik::available_input_plugins);
        NODE_SET_METHOD(target, "register_fonts", node_mapnik::register_fonts);
        NODE_SET_METHOD(target, "fonts", node_mapnik::available_font_faces);
        NODE_SET_METHOD(target, "fontFiles", node_mapnik::available_font_files);
        NODE_SET_METHOD(target, "clearCache", clearCache);
        NODE_SET_METHOD(target, "gc", gc);
        NODE_SET_METHOD(target, "shutdown",shutdown);

        // Classes
        VectorTile::Initialize(target);
        Map::Initialize(target);
        Color::Initialize(target);
        Geometry::Initialize(target);
        Feature::Initialize(target);
        Image::Initialize(target);
        ImageView::Initialize(target);
        Palette::Initialize(target);
        Projection::Initialize(target);
        ProjTransform::Initialize(target);
        Layer::Initialize(target);
        Grid::Initialize(target);
        GridView::Initialize(target);
        Datasource::Initialize(target);
        Featureset::Initialize(target);
        // Not production safe, so disabling indefinitely
        //JSDatasource::Initialize(target);
        MemoryDatasource::Initialize(target);
        #ifdef NODE_MAPNIK_EXPRESSION
        Expression::Initialize(target);
        #endif
        CairoSurface::Initialize(target);

        // versions of deps
        Local<Object> versions = Object::New();
        versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1)); // NOTE: +1 strips the v in v0.10.26
        versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
        versions->Set(String::NewSymbol("boost"), String::New(format_version(BOOST_VERSION).c_str()));
        versions->Set(String::NewSymbol("boost_number"), Integer::New(BOOST_VERSION));
        versions->Set(String::NewSymbol("mapnik"), String::New(format_version(MAPNIK_VERSION).c_str()));
        versions->Set(String::NewSymbol("mapnik_number"), Integer::New(MAPNIK_VERSION));
        versions->Set(String::NewSymbol("libxml"), String::New(LIBXML_DOTTED_VERSION));
#if defined(HAVE_CAIRO)
        versions->Set(String::NewSymbol("cairo"), String::New(CAIRO_VERSION_STRING));
#endif
        target->Set(String::NewSymbol("versions"), versions);

        Local<Object> supports = Object::New();
#if MAPNIK_VERSION >= 200300
        #ifdef GRID_RENDERER
        supports->Set(String::NewSymbol("grid"), True());
        #else
        supports->Set(String::NewSymbol("grid"), False());
        #endif
#else
        supports->Set(String::NewSymbol("grid"), True());
#endif

#ifdef SVG_RENDERER
        supports->Set(String::NewSymbol("svg"), True());
#else
        supports->Set(String::NewSymbol("svg"), False());
#endif

#if defined(HAVE_CAIRO)
        supports->Set(String::NewSymbol("cairo"), True());
        #ifdef CAIRO_HAS_PDF_SURFACE
        supports->Set(String::NewSymbol("cairo_pdf"), True());
        #else
        supports->Set(String::NewSymbol("cairo_pdf"), False());
        #endif
        #ifdef CAIRO_HAS_SVG_SURFACE
        supports->Set(String::NewSymbol("cairo_svg"), True());
        #else
        supports->Set(String::NewSymbol("cairo_svg"), False());
        #endif
#else
        supports->Set(String::NewSymbol("cairo"), False());
#endif

#if defined(HAVE_PNG)
        supports->Set(String::NewSymbol("png"), True());
#else
        supports->Set(String::NewSymbol("png"), False());
#endif

#if defined(HAVE_JPEG)
        supports->Set(String::NewSymbol("jpeg"), True());
#else
        supports->Set(String::NewSymbol("jpeg"), False());
#endif

#if defined(HAVE_TIFF)
        supports->Set(String::NewSymbol("tiff"), True());
#else
        supports->Set(String::NewSymbol("tiff"), False());
#endif

#if defined(HAVE_WEBP)
        supports->Set(String::NewSymbol("webp"), True());
#else
        supports->Set(String::NewSymbol("webp"), False());
#endif

#if defined(MAPNIK_USE_PROJ4)
        supports->Set(String::NewSymbol("proj4"), True());
#else
        supports->Set(String::NewSymbol("proj4"), False());
#endif

#if defined(MAPNIK_THREADSAFE)
        supports->Set(String::NewSymbol("threadsafe"), True());
#else
        supports->Set(String::NewSymbol("threadsafe"), False());
#endif

        target->Set(String::NewSymbol("supports"), supports);

#if MAPNIK_VERSION >= 200100
        Local<Object> composite_ops = Object::New();
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "clear", mapnik::clear)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src", mapnik::src)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst", mapnik::dst)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src_over", mapnik::src_over)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst_over", mapnik::dst_over)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src_in", mapnik::src_in)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst_in", mapnik::dst_in)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src_out", mapnik::src_out)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst_out", mapnik::dst_out)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src_atop", mapnik::src_atop)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst_atop", mapnik::dst_atop)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "xor", mapnik::_xor)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "plus", mapnik::plus)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "minus", mapnik::minus)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "multiply", mapnik::multiply)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "screen", mapnik::screen)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "overlay", mapnik::overlay)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "darken", mapnik::darken)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "lighten", mapnik::lighten)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "color_dodge", mapnik::color_dodge)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "color_burn", mapnik::color_burn)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "hard_light", mapnik::hard_light)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "soft_light", mapnik::soft_light)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "difference", mapnik::difference)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "exclusion", mapnik::exclusion)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "contrast", mapnik::contrast)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "invert", mapnik::invert)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "grain_merge", mapnik::grain_merge)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "grain_extract", mapnik::grain_extract)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "hue", mapnik::hue)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "saturation", mapnik::saturation)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "color", mapnik::_color)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "value", mapnik::_value)

        target->Set(String::NewSymbol("compositeOp"), composite_ops);
#endif
    }

}

} // namespace node_mapnik

// TODO - remove this hack at node v0.12.x
// https://github.com/joyent/node/commit/bd8a5755dceda415eee147bc06574f5a30abb0d0#commitcomment-5686345
#if NODE_VERSION_AT_LEAST(0, 9, 0)

#define NODE_MAPNIK_MODULE(modname, regfunc)                          \
  extern "C" {                                                        \
    MAPNIK_EXP node::node_module_struct modname ## _module =         \
    {                                                                 \
      NODE_STANDARD_MODULE_STUFF,                                     \
      (node::addon_register_func)regfunc,                             \
      NODE_STRINGIFY(modname)                                         \
    };                                                                \
  }

#else

#define NODE_MAPNIK_MODULE(modname, regfunc)                          \
  extern "C" {                                                        \
    MAPNIK_EXP node::node_module_struct modname ## _module =         \
    {                                                                 \
      NODE_STANDARD_MODULE_STUFF,                                     \
      regfunc,                             \
      NODE_STRINGIFY(modname)                                         \
    };                                                                \
  }

#endif

NODE_MAPNIK_MODULE(mapnik, node_mapnik::InitMapnik)
<commit_msg>disable ogr/gdal cleanup since it not viable to link or find gdal headers from node-mapnik - refs #251<commit_after>// v8
#include <v8.h>

// node
#include <node.h>
#include <node_version.h>
#include "mapnik3x_compatibility.hpp"

// node-mapnik
#include "mapnik_vector_tile.hpp"
#include "mapnik_map.hpp"
#include "mapnik_color.hpp"
#include "mapnik_geometry.hpp"
#include "mapnik_feature.hpp"
#include "mapnik_fonts.hpp"
#include "mapnik_plugins.hpp"
#include "mapnik_palette.hpp"
#include "mapnik_projection.hpp"
#include "mapnik_layer.hpp"
#include "mapnik_datasource.hpp"
#include "mapnik_featureset.hpp"
#include "mapnik_memory_datasource.hpp"
#include "mapnik_image.hpp"
#include "mapnik_image_view.hpp"
#include "mapnik_grid.hpp"
#include "mapnik_cairo_surface.hpp"
#include "mapnik_grid_view.hpp"
#ifdef NODE_MAPNIK_EXPRESSION
#include "mapnik_expression.hpp"
#endif
#include "utils.hpp"

#include <libxml/parser.h>
#include <libxml/xmlversion.h>

//#include <gdal_priv.h>
//#include <ogr_api.h>

// mapnik
#include <mapnik/config.hpp> // for MAPNIK_DECL
#include <mapnik/version.hpp>
#if MAPNIK_VERSION >= 200100
#include <mapnik/marker_cache.hpp>
#include <mapnik/mapped_memory_cache.hpp>
#include <mapnik/image_compositing.hpp>
#endif

// boost
#include <boost/version.hpp>

// cairo
#if defined(HAVE_CAIRO)
#include <cairo.h>
#endif

namespace node_mapnik {

using namespace node;
using namespace v8;

/**
 * Optional notification that the embedder is idle.
 * V8 uses the notification to reduce memory footprint.
 * This call can be used repeatedly if the embedder remains idle.
 * Returns true if the embedder should stop calling IdleNotification
 * until real work has been done.  This indicates that V8 has done
 * as much cleanup as it will be able to do.
 */
static Handle<Value> gc(const Arguments& args)
{
    HandleScope scope;
    return scope.Close(Boolean::New(V8::IdleNotification()));
}

static std::string format_version(int version)
{
    std::ostringstream s;
    s << version/100000 << "." << version/100 % 1000  << "." << version % 100;
    return s.str();
}

static Handle<Value> clearCache(const Arguments& args)
{
    HandleScope scope;
#if MAPNIK_VERSION >= 200300
    #if defined(SHAPE_MEMORY_MAPPED_FILE)
        mapnik::marker_cache::instance().clear();
        mapnik::mapped_memory_cache::instance().clear();
    #endif
#else
    #if MAPNIK_VERSION >= 200200
        mapnik::marker_cache::instance().clear();
        mapnik::mapped_memory_cache::instance().clear();
    #else
        #if MAPNIK_VERSION >= 200100
            mapnik::marker_cache::instance()->clear();
            mapnik::mapped_memory_cache::instance()->clear();
        #endif
    #endif
#endif
    return scope.Close(Undefined());
}

static Handle<Value> shutdown(const Arguments& args)
{
    HandleScope scope;
    google::protobuf::ShutdownProtobufLibrary();
    // http://lists.fedoraproject.org/pipermail/devel/2010-January/129117.html
    xmlCleanupParser();
    //GDALDestroyDriverManager();
    //OGRCleanupAll();
    return scope.Close(Undefined());
}

extern "C" {

    static void InitMapnik (Handle<Object> target)
    {
        HandleScope scope;
        GOOGLE_PROTOBUF_VERIFY_VERSION;
        // https://mail.gnome.org/archives/xml/2007-October/msg00004.html
        // calls http://xmlsoft.org/html/libxml-xmlversion.html#xmlCheckVersion
        // which internall calls http://xmlsoft.org/html/libxml-parser.html#xmlInitParser
        // see 'parserInternals.c' for details / requires xmlCleanupParser(); at exit
        LIBXML_TEST_VERSION;

        // module level functions
        NODE_SET_METHOD(target, "register_datasource", node_mapnik::register_datasource);
        NODE_SET_METHOD(target, "register_datasources", node_mapnik::register_datasources);
        NODE_SET_METHOD(target, "datasources", node_mapnik::available_input_plugins);
        NODE_SET_METHOD(target, "register_fonts", node_mapnik::register_fonts);
        NODE_SET_METHOD(target, "fonts", node_mapnik::available_font_faces);
        NODE_SET_METHOD(target, "fontFiles", node_mapnik::available_font_files);
        NODE_SET_METHOD(target, "clearCache", clearCache);
        NODE_SET_METHOD(target, "gc", gc);
        NODE_SET_METHOD(target, "shutdown",shutdown);

        // Classes
        VectorTile::Initialize(target);
        Map::Initialize(target);
        Color::Initialize(target);
        Geometry::Initialize(target);
        Feature::Initialize(target);
        Image::Initialize(target);
        ImageView::Initialize(target);
        Palette::Initialize(target);
        Projection::Initialize(target);
        ProjTransform::Initialize(target);
        Layer::Initialize(target);
        Grid::Initialize(target);
        GridView::Initialize(target);
        Datasource::Initialize(target);
        Featureset::Initialize(target);
        // Not production safe, so disabling indefinitely
        //JSDatasource::Initialize(target);
        MemoryDatasource::Initialize(target);
        #ifdef NODE_MAPNIK_EXPRESSION
        Expression::Initialize(target);
        #endif
        CairoSurface::Initialize(target);

        // versions of deps
        Local<Object> versions = Object::New();
        versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1)); // NOTE: +1 strips the v in v0.10.26
        versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
        versions->Set(String::NewSymbol("boost"), String::New(format_version(BOOST_VERSION).c_str()));
        versions->Set(String::NewSymbol("boost_number"), Integer::New(BOOST_VERSION));
        versions->Set(String::NewSymbol("mapnik"), String::New(format_version(MAPNIK_VERSION).c_str()));
        versions->Set(String::NewSymbol("mapnik_number"), Integer::New(MAPNIK_VERSION));
        versions->Set(String::NewSymbol("libxml"), String::New(LIBXML_DOTTED_VERSION));
#if defined(HAVE_CAIRO)
        versions->Set(String::NewSymbol("cairo"), String::New(CAIRO_VERSION_STRING));
#endif
        target->Set(String::NewSymbol("versions"), versions);

        Local<Object> supports = Object::New();
#if MAPNIK_VERSION >= 200300
        #ifdef GRID_RENDERER
        supports->Set(String::NewSymbol("grid"), True());
        #else
        supports->Set(String::NewSymbol("grid"), False());
        #endif
#else
        supports->Set(String::NewSymbol("grid"), True());
#endif

#ifdef SVG_RENDERER
        supports->Set(String::NewSymbol("svg"), True());
#else
        supports->Set(String::NewSymbol("svg"), False());
#endif

#if defined(HAVE_CAIRO)
        supports->Set(String::NewSymbol("cairo"), True());
        #ifdef CAIRO_HAS_PDF_SURFACE
        supports->Set(String::NewSymbol("cairo_pdf"), True());
        #else
        supports->Set(String::NewSymbol("cairo_pdf"), False());
        #endif
        #ifdef CAIRO_HAS_SVG_SURFACE
        supports->Set(String::NewSymbol("cairo_svg"), True());
        #else
        supports->Set(String::NewSymbol("cairo_svg"), False());
        #endif
#else
        supports->Set(String::NewSymbol("cairo"), False());
#endif

#if defined(HAVE_PNG)
        supports->Set(String::NewSymbol("png"), True());
#else
        supports->Set(String::NewSymbol("png"), False());
#endif

#if defined(HAVE_JPEG)
        supports->Set(String::NewSymbol("jpeg"), True());
#else
        supports->Set(String::NewSymbol("jpeg"), False());
#endif

#if defined(HAVE_TIFF)
        supports->Set(String::NewSymbol("tiff"), True());
#else
        supports->Set(String::NewSymbol("tiff"), False());
#endif

#if defined(HAVE_WEBP)
        supports->Set(String::NewSymbol("webp"), True());
#else
        supports->Set(String::NewSymbol("webp"), False());
#endif

#if defined(MAPNIK_USE_PROJ4)
        supports->Set(String::NewSymbol("proj4"), True());
#else
        supports->Set(String::NewSymbol("proj4"), False());
#endif

#if defined(MAPNIK_THREADSAFE)
        supports->Set(String::NewSymbol("threadsafe"), True());
#else
        supports->Set(String::NewSymbol("threadsafe"), False());
#endif

        target->Set(String::NewSymbol("supports"), supports);

#if MAPNIK_VERSION >= 200100
        Local<Object> composite_ops = Object::New();
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "clear", mapnik::clear)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src", mapnik::src)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst", mapnik::dst)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src_over", mapnik::src_over)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst_over", mapnik::dst_over)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src_in", mapnik::src_in)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst_in", mapnik::dst_in)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src_out", mapnik::src_out)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst_out", mapnik::dst_out)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "src_atop", mapnik::src_atop)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "dst_atop", mapnik::dst_atop)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "xor", mapnik::_xor)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "plus", mapnik::plus)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "minus", mapnik::minus)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "multiply", mapnik::multiply)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "screen", mapnik::screen)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "overlay", mapnik::overlay)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "darken", mapnik::darken)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "lighten", mapnik::lighten)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "color_dodge", mapnik::color_dodge)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "color_burn", mapnik::color_burn)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "hard_light", mapnik::hard_light)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "soft_light", mapnik::soft_light)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "difference", mapnik::difference)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "exclusion", mapnik::exclusion)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "contrast", mapnik::contrast)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "invert", mapnik::invert)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "grain_merge", mapnik::grain_merge)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "grain_extract", mapnik::grain_extract)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "hue", mapnik::hue)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "saturation", mapnik::saturation)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "color", mapnik::_color)
        NODE_MAPNIK_DEFINE_CONSTANT(composite_ops, "value", mapnik::_value)

        target->Set(String::NewSymbol("compositeOp"), composite_ops);
#endif
    }

}

} // namespace node_mapnik

// TODO - remove this hack at node v0.12.x
// https://github.com/joyent/node/commit/bd8a5755dceda415eee147bc06574f5a30abb0d0#commitcomment-5686345
#if NODE_VERSION_AT_LEAST(0, 9, 0)

#define NODE_MAPNIK_MODULE(modname, regfunc)                          \
  extern "C" {                                                        \
    MAPNIK_EXP node::node_module_struct modname ## _module =         \
    {                                                                 \
      NODE_STANDARD_MODULE_STUFF,                                     \
      (node::addon_register_func)regfunc,                             \
      NODE_STRINGIFY(modname)                                         \
    };                                                                \
  }

#else

#define NODE_MAPNIK_MODULE(modname, regfunc)                          \
  extern "C" {                                                        \
    MAPNIK_EXP node::node_module_struct modname ## _module =         \
    {                                                                 \
      NODE_STANDARD_MODULE_STUFF,                                     \
      regfunc,                             \
      NODE_STRINGIFY(modname)                                         \
    };                                                                \
  }

#endif

NODE_MAPNIK_MODULE(mapnik, node_mapnik::InitMapnik)
<|endoftext|>


<commit_before>#pragma once
// Compiler-provided
#include <thread>
#include <chrono>
#include <functional>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>

// External dependencies
#include <zmq.hpp>
#include <boost/algorithm/string.hpp>
#include "lib/spdlog/spdlog.h"

typedef struct ModuleInfo {
	std::string name = "undefined module";
	std::string author = "mainline";
} ModuleInfo;

enum class MgmtCommands {
	REGISTER,
	CLOSE
};

enum class SocketType {
	PUB,
	SUB,
	MGM_IN,
	MGM_OUT
};

class Module {
	protected:
		ModuleInfo __info;
		zmq::context_t* inp_context;
		zmq::socket_t* inp_manage_in;
		zmq::socket_t* inp_manage_out;
		zmq::socket_t* inp_in;
		zmq::socket_t* inp_out;
		std::shared_ptr<spdlog::logger> logger;
	public:
		virtual ~Module(){};
		virtual bool run()=0;
		virtual std::string name() {
			return this->__info.name;
		};
		void setLogger(const std::shared_ptr<spdlog::logger> loggerHandle) {
			this->logger = loggerHandle;
			this->logger->info("{}: Open", this->name());
		};
		void setSocketContext(zmq::context_t* context) {
			this->inp_context = context;
		};
		void openSockets() {
			std::string inPoint = "inproc://" + this->name() + ".in";
			std::string managePoint = "inproc://" + this->name() + ".manage";
			try {
				this->inp_in = new zmq::socket_t(*this->inp_context, ZMQ_SUB);
				this->inp_out = new zmq::socket_t(*this->inp_context, ZMQ_PUB);
				this->inp_manage_in = new zmq::socket_t(*this->inp_context, ZMQ_REP);
				this->inp_manage_out = new zmq::socket_t(*this->inp_context, ZMQ_REQ);

				this->inp_in->bind(inPoint.c_str());
				this->inp_manage_in->bind(managePoint.c_str());
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}
		};
		void closeSockets() {
			try {
				this->inp_in->close();
				this->inp_out->close();
				this->inp_manage_in->close();
				this->inp_manage_out->close();
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}

			delete this->inp_in;
			delete this->inp_out;
			delete this->inp_manage_in;
			delete this->inp_manage_out;
		};
		void notify(SocketType sockT, std::string endpoint) {
			endpoint = "inproc://" + endpoint;
			try {
				if (sockT == SocketType::PUB) {
					endpoint += ".in";
					this->inp_out->connect(endpoint.c_str());
				} else if (sockT == SocketType::MGM_OUT) {
					endpoint += ".manage";
					this->inp_manage_out->connect(endpoint.c_str());
				}
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}
		};
		void subscribe(std::string channel) {
			try{
				this->inp_in->setsockopt(ZMQ_SUBSCRIBE, channel.data(), channel.size());
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}
		};
		bool sendMessage(SocketType sockT, std::string message) {
			bool sendErr = false;

			zmq::message_t zmqObject(message.size());
			memcpy(zmqObject.data(), message.data(), message.size());

			try {
				if (sockT == SocketType::PUB) {
					sendErr = this->inp_out->send(zmqObject);
				} else if (sockT == SocketType::MGM_IN) {
					sendErr = this->inp_manage_in->send(zmqObject);
				} else if (sockT == SocketType::MGM_OUT) {
					sendErr = this->inp_manage_out->send(zmqObject);
				}
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}

			return sendErr;
		};
		std::string recvMessage(SocketType sockT, long timeout=1000) {
			return this->recvMessage<std::string>(
				sockT, [](const std::string& message) {
					return message;
				}, timeout
			);
		};
		template<typename retType>
		retType recvMessage(SocketType sockT,
							std::function<retType(const std::string&)> callback,
							long timeout=1000
		) {
			std::string messageText;

			zmq::socket_t* pollSocket;
			zmq::pollitem_t pollSocketItems[1];
			pollSocketItems[0].events = ZMQ_POLLIN;

			zmq::message_t message;
			bool recvErr = false;

			if (sockT == SocketType::PUB) {
				pollSocketItems[0].socket = *this->inp_in;
				pollSocket = this->inp_in;
			} else if (sockT == SocketType::MGM_IN) {
				pollSocketItems[0].socket = *this->inp_manage_in;
				pollSocket = this->inp_manage_in;
			} else if (sockT == SocketType::MGM_OUT) {
				pollSocketItems[0].socket = *this->inp_manage_out;
				pollSocket = this->inp_manage_out;
			}

			int data = zmq::poll(pollSocketItems, 1, timeout);
			if (data > 0) {
				recvErr = pollSocket->recv(&message);
			}

			if(recvErr) {
				messageText = std::string(static_cast<char*>(message.data()), message.size());
			}

			return callback(messageText);
		};
};

typedef Module* Module_loader(void);
typedef void Module_unloader(Module*);<commit_msg>Better logging and include ordering<commit_after>#pragma once
// Common
#include <string>
#include <sstream>
#include <iostream>
#include <vector>

#include <thread>
#include <chrono>
#include <functional>

#include <zmq.hpp>
#include <boost/algorithm/string.hpp>
// Module Specific
#include "lib/spdlog/spdlog.h"

typedef struct ModuleInfo {
	std::string name = "undefined module";
	std::string author = "mainline";
} ModuleInfo;

enum class MgmtCommands {
	REGISTER,
	CLOSE
};

enum class SocketType {
	PUB,
	SUB,
	MGM_IN,
	MGM_OUT
};

class Module {
	protected:
		ModuleInfo __info;
		zmq::context_t* inp_context;
		zmq::socket_t* inp_manage_in;
		zmq::socket_t* inp_manage_out;
		zmq::socket_t* inp_in;
		zmq::socket_t* inp_out;
		std::shared_ptr<spdlog::logger> logger;
	public:
		virtual ~Module(){};
		virtual bool run()=0;
		virtual std::string name() {
			return this->__info.name;
		};
		void setLogger(const std::shared_ptr<spdlog::logger> loggerHandle) {
			this->logger = loggerHandle;
			this->logger->debug("{}: Logger Open", this->name());
		};
		void setSocketContext(zmq::context_t* context) {
			this->inp_context = context;
		};
		void openSockets() {
			std::string inPoint = "inproc://" + this->name() + ".in";
			std::string managePoint = "inproc://" + this->name() + ".manage";
			try {
				this->inp_in = new zmq::socket_t(*this->inp_context, ZMQ_SUB);
				this->inp_out = new zmq::socket_t(*this->inp_context, ZMQ_PUB);
				this->inp_manage_in = new zmq::socket_t(*this->inp_context, ZMQ_REP);
				this->inp_manage_out = new zmq::socket_t(*this->inp_context, ZMQ_REQ);

				this->inp_in->bind(inPoint.c_str());
				this->inp_manage_in->bind(managePoint.c_str());
				this->logger->debug("{}: Sockets Open", this->name());
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}
		};
		void closeSockets() {
			try {
				this->inp_in->close();
				this->inp_out->close();
				this->inp_manage_in->close();
				this->inp_manage_out->close();
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}

			delete this->inp_in;
			delete this->inp_out;
			delete this->inp_manage_in;
			delete this->inp_manage_out;
		};
		void notify(SocketType sockT, std::string endpoint) {
			endpoint = "inproc://" + endpoint;
			try {
				if (sockT == SocketType::PUB) {
					endpoint += ".in";
					this->inp_out->connect(endpoint.c_str());
				} else if (sockT == SocketType::MGM_OUT) {
					endpoint += ".manage";
					this->inp_manage_out->connect(endpoint.c_str());
				}
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}
		};
		void subscribe(std::string channel) {
			try{
				this->inp_in->setsockopt(ZMQ_SUBSCRIBE, channel.data(), channel.size());
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}
		};
		bool sendMessage(SocketType sockT, std::string message) {
			bool sendErr = false;

			zmq::message_t zmqObject(message.size());
			memcpy(zmqObject.data(), message.data(), message.size());

			try {
				if (sockT == SocketType::PUB) {
					sendErr = this->inp_out->send(zmqObject);
				} else if (sockT == SocketType::MGM_IN) {
					sendErr = this->inp_manage_in->send(zmqObject);
				} else if (sockT == SocketType::MGM_OUT) {
					sendErr = this->inp_manage_out->send(zmqObject);
				}
			} catch (const zmq::error_t &e) {
				std::cout << e.what() << std::endl;
			}

			return sendErr;
		};
		std::string recvMessage(SocketType sockT, long timeout=1000) {
			return this->recvMessage<std::string>(
				sockT, [](const std::string& message) {
					return message;
				}, timeout
			);
		};
		template<typename retType>
		retType recvMessage(SocketType sockT,
							std::function<retType(const std::string&)> callback,
							long timeout=1000
		) {
			std::string messageText;

			zmq::socket_t* pollSocket;
			zmq::pollitem_t pollSocketItems[1];
			pollSocketItems[0].events = ZMQ_POLLIN;

			zmq::message_t message;
			bool recvErr = false;

			if (sockT == SocketType::PUB) {
				pollSocketItems[0].socket = *this->inp_in;
				pollSocket = this->inp_in;
			} else if (sockT == SocketType::MGM_IN) {
				pollSocketItems[0].socket = *this->inp_manage_in;
				pollSocket = this->inp_manage_in;
			} else if (sockT == SocketType::MGM_OUT) {
				pollSocketItems[0].socket = *this->inp_manage_out;
				pollSocket = this->inp_manage_out;
			}

			int data = zmq::poll(pollSocketItems, 1, timeout);
			if (data > 0) {
				recvErr = pollSocket->recv(&message);
			}

			if(recvErr) {
				messageText = std::string(static_cast<char*>(message.data()), message.size());
			}

			return callback(messageText);
		};
};

typedef Module* Module_loader(void);
typedef void Module_unloader(Module*);<|endoftext|>


<commit_before>//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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
// General Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.

#ifndef __math_sincos_hpp__
#define __math_sincos_hpp__

#include <cmath>

#ifdef __linux__
#define SINCOS sincos
#elif __APPLE__
#define SINCOS __sincos
#endif

#endif //#ifndef __math_sincos_hpp__
<commit_msg>[C++] Implement SINCOS macro for QNX.<commit_after>//
// Copyright (c) 2015 CNRS
//
// This file is part of Pinocchio
// Pinocchio is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// Pinocchio 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
// General Lesser Public License for more details. You should have
// received a copy of the GNU Lesser General Public License along with
// Pinocchio If not, see
// <http://www.gnu.org/licenses/>.

#ifndef __math_sincos_hpp__
#define __math_sincos_hpp__

#include <cmath>

#ifdef __linux__
#define SINCOS sincos
#elif __APPLE__
#define SINCOS __sincos
#elif __QNXNTO__
#define SINCOS(a,sa,ca) (*sa) = std::sin(a); (*ca) = std::cos(a)
#endif

#endif //#ifndef __math_sincos_hpp__
<|endoftext|>


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

 Program: FEMUS
 Module: MED_IO
 Authors: Sureka Pathmanathan, Giorgio Bornia

 Copyright (c) FEMTTU
 All rights reserved.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notice for more information.

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

#ifndef __femus_mesh_MED_IO_hpp__
#define __femus_mesh_MED_IO_hpp__

// Local includes
#include "MeshInput.hpp"
#include "GeomElTypeEnum.hpp"
#include "GeomElemBase.hpp"
#include "GeomElemHex27.hpp"
#include "GeomElemTet10.hpp"
#include "GeomElemQuad9.hpp"
#include "GeomElemTri6.hpp"
#include "GeomElemEdge3.hpp"

#ifdef HAVE_HDF5
  #include "hdf5.h"
#endif

namespace femus
{

 #define TYPE_FOR_FAM_FLAGS  int  //do not use "unsigned" because these numbers in MED are NEGATIVE!

// Auxiliary struct to store group information
  struct GroupInfo {
      TYPE_FOR_FAM_FLAGS _med_flag;
      int _user_defined_flag;
      int _user_defined_property;
      GeomElemBase* _geom_el;
      int _size;
  };

// Forward declarations
class Mesh;

/**
 * This class implements reading meshes in the MED format.
 */

// ------------------------------------------------------------
class MED_IO : public MeshInput<Mesh>
{
 public:

  /**
   * Constructor.  Takes a non-const Mesh reference which it
   * will fill up with elements via the read() command.
   */
  explicit
  MED_IO (Mesh& mesh);

//   ~MED_IO();

  /**
   * Reads in a mesh in the neutral gambit *.neu format
   * from the ASCII file given by name.
   *
   */
  virtual void read (const std::string& name, vector < vector < double> > &coords, const double Lref, std::vector<bool> &type_elem_flag);

 private:

   unsigned int get_user_flag_from_med_flag(const std::vector< GroupInfo > & group_info, const TYPE_FOR_FAM_FLAGS med_flag_in ) const;

   void set_elem_group_ownership(const hid_t&  file_id, const std::string mesh_menu, const int i,  const GeomElemBase* geom_elem_per_dimension, const std::vector<GroupInfo> & group_info);

   void compute_group_geom_elem_and_size(const hid_t&  file_id, const std::string mesh_menu, GroupInfo & group_info)  const;

   void set_elem_connectivity(const hid_t&  file_id, const std::string mesh_menu, const unsigned i, const GeomElemBase* geom_elem_per_dimension, std::vector<bool>& type_elem_flag);

   void find_boundary_faces_and_set_face_flags(const hid_t&  file_id, const std::string mesh_menu, const GeomElemBase* geom_elem_per_dimension, const std::vector<GroupInfo> & group_info);

   void set_node_coordinates(const hid_t&  file_id, const std::string mesh_menu, vector < vector < double> >& coords, const double Lref);

   const GroupInfo                get_group_flags_per_mesh(const std::string & group_names) const;

   const std::vector< GroupInfo > get_group_vector_flags_per_mesh(const hid_t &  file_id, const std::string & mesh_menu) const;

   const std::vector<std::string>  get_mesh_names(const hid_t & file_id) const;

   std::pair<int,int>  isolate_number_in_string(const std::string & string_in, const int begin_pos_to_investigate) const;

   /** Determine mesh dimension from mesh file */
   const std::vector< GeomElemBase* >  set_mesh_dimension_and_get_geom_elems_by_looping_over_element_types(const hid_t &  file_id, const std::string & menu_name); //this cannot be const because it sets the dimension in the mesh

   GeomElemBase * get_geom_elem_from_med_name(const  std::string el_type) const;

   /** Read FE type */
  const std::vector< GeomElemBase* > get_geom_elem_type_per_dimension(const hid_t & file_id, const std::string my_mesh_name_dir);   //@todo this should be const

   /** Map from Salome vertex index to Femus vertex index */
   static const unsigned MEDToFemusVertexIndex[N_GEOM_ELS][MAX_EL_N_NODES];

   /** Map from Salome face index to Femus face index */
   static const unsigned MEDToFemusFaceIndex[N_GEOM_ELS][MAX_EL_N_FACES];

//    std::vector<char*> menu_names;
   static const std::string mesh_ensemble;             //ENS_MAA
   static const std::string aux_zeroone;               // -0000000000000000001-0000000000000000001
   static const std::string elem_list;                 //MAI
   static const std::string group_fam;                 //FAM
   static const std::string connectivity;              //NOD    //These are written based on the NOE/NUM numbering !
   static const std::string node_or_elem_global_num;   //NUM    //this is the MED global numbering (as you see in Salome) both for nodes (in NOE) and for elements of all dimensions (in MAI).
                                                       //Salome global Numbering of both Nodes and Elements starts at 1.
                                                       //For Elements, lower dimensional elements are numbered first
   static const std::string node_list;                 //NOE
   static const std::string coord_list;                //COO
   static const std::string group_ensemble;            //FAS
   static const std::string group_elements;            //ELEME
   static const std::string group_nodes;               //NOEUD  //if you ever use group of nodes, not used now
   static const uint max_length;

   std::vector< GeomElemBase* > _geom_elems;

};

inline
MED_IO::MED_IO (Mesh& mesh) :
   MeshInput<Mesh>  (mesh)
{

       _geom_elems.resize(N_GEOM_ELS);

       _geom_elems[0] = new GeomElemHex27();
       _geom_elems[1] = new GeomElemTet10();
//        _geom_elems[2] = new GeomElemWedge18();
       _geom_elems[3] = new GeomElemQuad9();
       _geom_elems[4] = new GeomElemTri6();
       _geom_elems[5] = new GeomElemEdge3();

}

// MED_IO::~MED_IO() {
//
//         for(unsigned g = 0; g < _geom_elems.size(); g++) delete _geom_elems[g];
//
// }

// @todo hybrid meshes (MED can export them)
// @todo groups with more than one type of element (in the sense hybrid, but at the same dimension)
// @todo mesh with overlapping groups  (MED can export them, defining the intersection independently; now the name parsing wouldn't work with them; Salome splits into non-intersecting family, so one needs to read the GRO/NOM dataset )
// @todo how would I use a 0d element? or a ball?
// @todo triggering of the copy of new input files happens right after "Configure" of cmake
// @todo Redirect CERR together with COUT
// @todo Update Xdmf to Xdmf3
// @todo not running in parallel
// @todo I know I can make only groups of edges/faces/volumes, but can I do hybrid faces, say quad and tri together?
// @todo Generate MED format from other software such as Gmsh
// @todo FEHex20, FEQuad8, FETri7 missing

} // namespace femus

#endif
<commit_msg>added H5Tpublic.h<commit_after>/*=========================================================================

 Program: FEMUS
 Module: MED_IO
 Authors: Sureka Pathmanathan, Giorgio Bornia

 Copyright (c) FEMTTU
 All rights reserved.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notice for more information.

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

#ifndef __femus_mesh_MED_IO_hpp__
#define __femus_mesh_MED_IO_hpp__

// Local includes
#include "MeshInput.hpp"
#include "GeomElTypeEnum.hpp"
#include "GeomElemBase.hpp"
#include "GeomElemHex27.hpp"
#include "GeomElemTet10.hpp"
#include "GeomElemQuad9.hpp"
#include "GeomElemTri6.hpp"
#include "GeomElemEdge3.hpp"

#ifdef HAVE_HDF5
  #include "hdf5.h"
  #include "H5Tpublic.h"
#endif

namespace femus
{

 #define TYPE_FOR_FAM_FLAGS  int  //do not use "unsigned" because these numbers in MED are NEGATIVE!

// Auxiliary struct to store group information
  struct GroupInfo {
      TYPE_FOR_FAM_FLAGS _med_flag;
      int _user_defined_flag;
      int _user_defined_property;
      GeomElemBase* _geom_el;
      int _size;
  };

// Forward declarations
class Mesh;

/**
 * This class implements reading meshes in the MED format.
 */

// ------------------------------------------------------------
class MED_IO : public MeshInput<Mesh>
{
 public:

  /**
   * Constructor.  Takes a non-const Mesh reference which it
   * will fill up with elements via the read() command.
   */
  explicit
  MED_IO (Mesh& mesh);

//   ~MED_IO();

  /**
   * Reads in a mesh in the neutral gambit *.neu format
   * from the ASCII file given by name.
   *
   */
  virtual void read (const std::string& name, vector < vector < double> > &coords, const double Lref, std::vector<bool> &type_elem_flag);

 private:

   unsigned int get_user_flag_from_med_flag(const std::vector< GroupInfo > & group_info, const TYPE_FOR_FAM_FLAGS med_flag_in ) const;

   void set_elem_group_ownership(const hid_t&  file_id, const std::string mesh_menu, const int i,  const GeomElemBase* geom_elem_per_dimension, const std::vector<GroupInfo> & group_info);

   void compute_group_geom_elem_and_size(const hid_t&  file_id, const std::string mesh_menu, GroupInfo & group_info)  const;

   void set_elem_connectivity(const hid_t&  file_id, const std::string mesh_menu, const unsigned i, const GeomElemBase* geom_elem_per_dimension, std::vector<bool>& type_elem_flag);

   void find_boundary_faces_and_set_face_flags(const hid_t&  file_id, const std::string mesh_menu, const GeomElemBase* geom_elem_per_dimension, const std::vector<GroupInfo> & group_info);

   void set_node_coordinates(const hid_t&  file_id, const std::string mesh_menu, vector < vector < double> >& coords, const double Lref);

   const GroupInfo                get_group_flags_per_mesh(const std::string & group_names) const;

   const std::vector< GroupInfo > get_group_vector_flags_per_mesh(const hid_t &  file_id, const std::string & mesh_menu) const;

   const std::vector<std::string>  get_mesh_names(const hid_t & file_id) const;

   std::pair<int,int>  isolate_number_in_string(const std::string & string_in, const int begin_pos_to_investigate) const;

   /** Determine mesh dimension from mesh file */
   const std::vector< GeomElemBase* >  set_mesh_dimension_and_get_geom_elems_by_looping_over_element_types(const hid_t &  file_id, const std::string & menu_name); //this cannot be const because it sets the dimension in the mesh

   GeomElemBase * get_geom_elem_from_med_name(const  std::string el_type) const;

   /** Read FE type */
  const std::vector< GeomElemBase* > get_geom_elem_type_per_dimension(const hid_t & file_id, const std::string my_mesh_name_dir);   //@todo this should be const

   /** Map from Salome vertex index to Femus vertex index */
   static const unsigned MEDToFemusVertexIndex[N_GEOM_ELS][MAX_EL_N_NODES];

   /** Map from Salome face index to Femus face index */
   static const unsigned MEDToFemusFaceIndex[N_GEOM_ELS][MAX_EL_N_FACES];

//    std::vector<char*> menu_names;
   static const std::string mesh_ensemble;             //ENS_MAA
   static const std::string aux_zeroone;               // -0000000000000000001-0000000000000000001
   static const std::string elem_list;                 //MAI
   static const std::string group_fam;                 //FAM
   static const std::string connectivity;              //NOD    //These are written based on the NOE/NUM numbering !
   static const std::string node_or_elem_global_num;   //NUM    //this is the MED global numbering (as you see in Salome) both for nodes (in NOE) and for elements of all dimensions (in MAI).
                                                       //Salome global Numbering of both Nodes and Elements starts at 1.
                                                       //For Elements, lower dimensional elements are numbered first
   static const std::string node_list;                 //NOE
   static const std::string coord_list;                //COO
   static const std::string group_ensemble;            //FAS
   static const std::string group_elements;            //ELEME
   static const std::string group_nodes;               //NOEUD  //if you ever use group of nodes, not used now
   static const uint max_length;

   std::vector< GeomElemBase* > _geom_elems;

};

inline
MED_IO::MED_IO (Mesh& mesh) :
   MeshInput<Mesh>  (mesh)
{

       _geom_elems.resize(N_GEOM_ELS);

       _geom_elems[0] = new GeomElemHex27();
       _geom_elems[1] = new GeomElemTet10();
//        _geom_elems[2] = new GeomElemWedge18();
       _geom_elems[3] = new GeomElemQuad9();
       _geom_elems[4] = new GeomElemTri6();
       _geom_elems[5] = new GeomElemEdge3();

}

// MED_IO::~MED_IO() {
//
//         for(unsigned g = 0; g < _geom_elems.size(); g++) delete _geom_elems[g];
//
// }

// @todo hybrid meshes (MED can export them)
// @todo groups with more than one type of element (in the sense hybrid, but at the same dimension)
// @todo mesh with overlapping groups  (MED can export them, defining the intersection independently; now the name parsing wouldn't work with them; Salome splits into non-intersecting family, so one needs to read the GRO/NOM dataset )
// @todo how would I use a 0d element? or a ball?
// @todo triggering of the copy of new input files happens right after "Configure" of cmake
// @todo Redirect CERR together with COUT
// @todo Update Xdmf to Xdmf3
// @todo not running in parallel
// @todo I know I can make only groups of edges/faces/volumes, but can I do hybrid faces, say quad and tri together?
// @todo Generate MED format from other software such as Gmsh
// @todo FEHex20, FEQuad8, FETri7 missing

} // namespace femus

#endif
<|endoftext|>


<commit_before>#include "./meshes_node.h"
#include <string>
#include "./importer.h"
#include "./graphics/gl.h"

MeshesNode::MeshesNode(std::string assetFilename,
                       Eigen::Matrix4f transformation)
  : assetFilename(assetFilename), transformation(transformation)
{
  // obb = mesh->obb * transformation;
}

MeshesNode::~MeshesNode()
{
}

void MeshesNode::render(Graphics::Gl *gl,
                        std::shared_ptr<Graphics::Managers> managers,
                        RenderData renderData)
{
  if (meshes.size() == 0)
    loadMeshes();

  if (!isVisible)
    return;

  for (auto &mesh : meshes)
  {
    renderData.modelMatrix = transformation;
    mesh->render(gl, managers, renderData);
  }
}

Eigen::Matrix4f MeshesNode::getTransformation()
{
  return this->transformation;
}

void MeshesNode::setTransformation(Eigen::Matrix4f transformation)
{
  this->transformation = transformation;
}

void MeshesNode::loadMeshes()
{
  Importer importer;

  meshes = importer.importAll(assetFilename);
  for (size_t index = 0; index < meshes.size(); ++index)
  {
    transformations.push_back(
        importer.getTransformationFor(assetFilename, index));
  }
}

<commit_msg>Calculate obb for MeshesNode.<commit_after>#include "./meshes_node.h"
#include <string>
#include "./importer.h"
#include "./graphics/gl.h"

MeshesNode::MeshesNode(std::string assetFilename,
                       Eigen::Matrix4f transformation)
  : assetFilename(assetFilename), transformation(transformation)
{
}

MeshesNode::~MeshesNode()
{
}

void MeshesNode::render(Graphics::Gl *gl,
                        std::shared_ptr<Graphics::Managers> managers,
                        RenderData renderData)
{
  if (meshes.size() == 0)
    loadMeshes();

  if (!isVisible)
    return;

  for (auto &mesh : meshes)
  {
    renderData.modelMatrix = transformation;
    mesh->render(gl, managers, renderData);
  }
}

Eigen::Matrix4f MeshesNode::getTransformation()
{
  return this->transformation;
}

void MeshesNode::setTransformation(Eigen::Matrix4f transformation)
{
  this->transformation = transformation;
}

void MeshesNode::loadMeshes()
{
  Importer importer;

  meshes = importer.importAll(assetFilename);
  Eigen::MatrixXf data(3, 8 * meshes.size());
  size_t cornerIndex = 0;
  for (size_t index = 0; index < meshes.size(); ++index)
  {
    transformations.push_back(
        importer.getTransformationFor(assetFilename, index));

    for (auto &corner : meshes[index]->obb.corners)
      data.col(cornerIndex++) = corner;
  }

  obb = Math::Obb(data) * transformation;
}

<|endoftext|>


<commit_before>#include "Logger.h"
//Not sure why these should be here, they're also in Logger.h... but it won't compile without them.
using std::endl;
using std::string;
using std::vector;
using std::unordered_map;
using std::ofstream;
using std::stringstream;

namespace ADBLib
{
	/**
	 * @brief Constructor for log.
	 * @param newName the name of the log as referred to when grabbed by Logger.
	 * @param newFileName The filename for the log file. Do NOT append any file extension, it does it for you.
	 * @note If on a linux-based system (such as a roboRIO), you need to add "/" to the beginning of the filename.
	 */
    Log::Log(string newName, string newFilename)
    {
        name = newName;
        filename = newFilename;
        log("Init creation of logfile " + filename);
    }

    /**
     * @brief Log a message with a timestamp and the given flag.
     * @param message The message to be logged.
     * @param flag This message's flag.
     */
    void Log::log(string message, logFlag flag)
    {
        //Output time for logging purposes
        time_t rawTime;
        tm* timeInfo;
        time(&rawTime);
        timeInfo = localtime(&rawTime);

        string flagText;
        switch (flag)
        {
        case error:
            flagText = "[ERROR]\t\t";
            break;
        case info:
            flagText = "[INFO]\t\t";
            break;
        case resource:
            flagText = "[RESOURCE]\t";
            break;
        case hydsys:
            flagText = "[SYSTEM]\t";
            break;
        default:
            flagText = "[NOFLAG]\t";
            break;
        }

        stringstream logEntry;
        logEntry << "[" << timeInfo->tm_hour << ":" << timeInfo->tm_min << ":" << timeInfo->tm_sec << "]\t";
        logEntry << flagText;
        logEntry << message;
        logBuffer.push_back(logEntry.str());
        if (logBuffer.size() >= MAX_LOGBUFFER_ENTRIES)
            flushBuffer();
    }

    /** Flush the log buffer, outputting all messages to file.
     * Log buffers are used to reduce lag from files constantly being opened and closed, because fstream is wierd.
     */
    void Log::flushBuffer()
    {
        //TODO: Have this operate in a separate thread (for efficiency)
        ofstream file;
        file.open(filename);
        for (auto iter = logBuffer.begin(); iter != logBuffer.end(); iter++)
            file << *iter << endl;
    }

    unordered_map<string, Log> Logger::logFiles;

    Logger::Logger()
    {
    }

    /**
     * @brief Logs a message to the log designated log.
     * @param message The message to log.
     * @param flag The flag of the message.
     * @param name The name of the log to log to.
     */
    void Logger::log(string message, string name, logFlag flag)
    {
    	if (logFiles.count(name) == 0)
    	{
    		//No log file exists
    		log("Cannot find log " + name + ", creating new one at." + name + ".txt", "sysLog", info);
    		Log newLog(name, name);
    		logFiles[name] = newLog;
    	}
    	logFiles[name].log(message, flag);
    }

    /**
     * @brief Creates a new log with the given name and filename.
     * @param name The name of the log to create.
     * @param filename The file to write to. Do NOT append a file extension, it does it for you.
     */
    void Logger::newLog(string name, string filename)
    {
    	if (logFiles.count(name) > 0)
    		return; //Duplicate logfile found
        Log _newLog(name, filename);
        logFiles[name] = _newLog;
    }

    /**
     * @brief Gets a pointer to a log of the given name.
     * @param name The name of the log.
     * @return Pointer to the log object. Returns nullptr if the log does not exist.
     */
    Log* Logger::getLog(string name)
    {
        if (logFiles.count(name) == 0)
        	return nullptr;
        return &logFiles[name];
    }

    /**
     * @brief Flush all log buffers, outputting ALL logs to text.
     */
    void Logger::flushLogBuffers()
    {
    	for (auto iter = logFiles.begin(); iter != logFiles.end(); iter++)
    		iter->second.flushBuffer(); //unordered_map iteration gives you an std::pair object
    }
};
<commit_msg>Fix Logger automatic creation of log files, add reminder note to docs<commit_after>#include "Logger.h"
//Not sure why these should be here, they're also in Logger.h... but it won't compile without them.
using std::endl;
using std::string;
using std::vector;
using std::unordered_map;
using std::ofstream;
using std::stringstream;

namespace ADBLib
{
	/**
	 * @brief Constructor for log.
	 * @param newName the name of the log as referred to when grabbed by Logger.
	 * @param newFileName The filename for the log file. Do NOT append any file extension, it does it for you.
	 * @note If on a linux-based system (such as a roboRIO), you need to add "/" to the beginning of the filename.
	 */
    Log::Log(string newName, string newFilename)
    {
        name = newName;
        filename = newFilename;
        log("Init creation of logfile " + filename);
    }

    /**
     * @brief Log a message with a timestamp and the given flag.
     * @param message The message to be logged.
     * @param flag This message's flag.
     */
    void Log::log(string message, logFlag flag)
    {
        //Output time for logging purposes
        time_t rawTime;
        tm* timeInfo;
        time(&rawTime);
        timeInfo = localtime(&rawTime);

        string flagText;
        switch (flag)
        {
        case error:
            flagText = "[ERROR]\t\t";
            break;
        case info:
            flagText = "[INFO]\t\t";
            break;
        case resource:
            flagText = "[RESOURCE]\t";
            break;
        case hydsys:
            flagText = "[SYSTEM]\t";
            break;
        default:
            flagText = "[NOFLAG]\t";
            break;
        }

        stringstream logEntry;
        logEntry << "[" << timeInfo->tm_hour << ":" << timeInfo->tm_min << ":" << timeInfo->tm_sec << "]\t";
        logEntry << flagText;
        logEntry << message;
        logBuffer.push_back(logEntry.str());
        if (logBuffer.size() >= MAX_LOGBUFFER_ENTRIES)
            flushBuffer();
    }

    /** Flush the log buffer, outputting all messages to file.
     * Log buffers are used to reduce lag from files constantly being opened and closed, because fstream is wierd.
     */
    void Log::flushBuffer()
    {
        //TODO: Have this operate in a separate thread (for efficiency)
        ofstream file;
        file.open(filename);
        for (auto iter = logBuffer.begin(); iter != logBuffer.end(); iter++)
            file << *iter << endl;
    }

    unordered_map<string, Log> Logger::logFiles;

    Logger::Logger()
    {
    }

    /**
     * @brief Logs a message to the log designated log.
     * @param message The message to log.
     * @param flag The flag of the message.
     * @param name The name of the log to log to.
     */
    void Logger::log(string message, string name, logFlag flag)
    {
    	if (logFiles.count(name) == 0)
    	{
    		//No log file exists
    		log("Cannot find log " + name + ", creating new one at /" + name + ".txt", "sysLog", info);
    		Log newLog(name, "/" + name + ".txt");
    		logFiles[name] = newLog;
    	}
    	logFiles[name].log(message, flag);
    }

    /**
     * @brief Creates a new log with the given name and filename.
     * @param name The name of the log to create.
     * @param filename The file to write to.
     * @note Don't forget a leading '/' on the filename.
     */
    void Logger::newLog(string name, string filename)
    {
    	if (logFiles.count(name) > 0)
    		return; //Duplicate logfile found
        Log _newLog(name, filename);
        logFiles[name] = _newLog;
    }

    /**
     * @brief Gets a pointer to a log of the given name.
     * @param name The name of the log.
     * @return Pointer to the log object. Returns nullptr if the log does not exist.
     */
    Log* Logger::getLog(string name)
    {
        if (logFiles.count(name) == 0)
        	return nullptr;
        return &logFiles[name];
    }

    /**
     * @brief Flush all log buffers, outputting ALL logs to text.
     */
    void Logger::flushLogBuffers()
    {
    	for (auto iter = logFiles.begin(); iter != logFiles.end(); iter++)
    		iter->second.flushBuffer(); //unordered_map iteration gives you an std::pair object
    }
};
<|endoftext|>


<commit_before>#include "model/World.h"
#include "model/PhysicsWorld.h"

#include <fstream>
#include <iostream>
#include <sstream>

namespace Rally { namespace Model {

    World::World() :
            physicsWorld(),
            playerCar(physicsWorld),
			finish(physicsWorld),
			start(physicsWorld),
            tunnelTeleport(physicsWorld) {
    }

    World::~World() {
    }

    void World::initialize(const std::string & bulletFile) {
        physicsWorld.initialize(bulletFile);
        playerCar.attachToWorld();
		finish.attachToWorld(btVector3(-1.3f, 0.f, -1.1f), btVector3(0.1f, 6.f, 3.2f));
		start.attachToWorld(btVector3(113.0f, 0.f, 183.0f), btVector3(10.f, 10.f, 10.f));
        tunnelTeleport.attachToWorld(btVector3(90.0f, 1.5f, -134.0f), btVector3(3.f, 3.f, 3.f));
        finishTimer.reset();
		start.collide();
		highScore = 200;

    }

    void World::update(float deltaTime) {
        physicsWorld.update(deltaTime);

        Rally::Vector3 playerCarPosition = playerCar.getPosition();
        if(playerCarPosition.y < -20.0f) {
            playerCar.teleport(Rally::Vector3(playerCarPosition.x, 30.0f, playerCarPosition.z),
                playerCar.getOrientation(),
                false);
        }

        if(tunnelTeleport.hasCollided()) {
            playerCar.teleport(Rally::Vector3(-126.0f, -4.0f, -52.0f),
                Rally::Quaternion(1.0f, 0.0f, 0.0f, 0.0f),
                true);
            tunnelTeleport.setEnabled(false);
        }

		printFinishedTime();

    }

	void World::printFinishedTime(){
		if(!start.hasCollided())
			finish.reset();

		if(start.hasCollided() && finish.hasCollided() && finish.isEnabled()){
			//finish.setEnabled(false);
			if(finishTimer.getElapsedSeconds() > 2)
			  std::cout << "Finished after: " << finishTimer.getElapsedSeconds() << " seconds!" << std::endl;
			lastTime = finishTimer.getElapsedSeconds();
			if(highScore == 200)
				highScore = 199;
			else if(lastTime < highScore)
				highScore = lastTime;
			finish.reset();
			start.reset();
			finishTimer.reset();

		}
	}

	float World::getElapsedSeconds(){
	    return finishTimer.getElapsedSeconds();
	}

	float World::getLastTime(){
		return lastTime;
	}

	float World::getHighScore(){
		return highScore;
	}

	void World::resetHighScore(){
		highScore = 200;
	}
} }
<commit_msg>Last time now defaults to zero<commit_after>#include "model/World.h"
#include "model/PhysicsWorld.h"

#include <fstream>
#include <iostream>
#include <sstream>

namespace Rally { namespace Model {

    World::World() :
            physicsWorld(),
            playerCar(physicsWorld),
			finish(physicsWorld),
			start(physicsWorld),
            tunnelTeleport(physicsWorld) {
    }

    World::~World() {
    }

    void World::initialize(const std::string & bulletFile) {
        physicsWorld.initialize(bulletFile);
        playerCar.attachToWorld();
		finish.attachToWorld(btVector3(-1.3f, 0.f, -1.1f), btVector3(0.1f, 6.f, 3.2f));
		start.attachToWorld(btVector3(113.0f, 0.f, 183.0f), btVector3(10.f, 10.f, 10.f));
        tunnelTeleport.attachToWorld(btVector3(90.0f, 1.5f, -134.0f), btVector3(3.f, 3.f, 3.f));
        finishTimer.reset();
		start.collide();
		highScore = 200;
        lastTime = 0;
    }

    void World::update(float deltaTime) {
        physicsWorld.update(deltaTime);

        Rally::Vector3 playerCarPosition = playerCar.getPosition();
        if(playerCarPosition.y < -20.0f) {
            playerCar.teleport(Rally::Vector3(playerCarPosition.x, 30.0f, playerCarPosition.z),
                playerCar.getOrientation(),
                false);
        }

        if(tunnelTeleport.hasCollided()) {
            playerCar.teleport(Rally::Vector3(-126.0f, -4.0f, -52.0f),
                Rally::Quaternion(1.0f, 0.0f, 0.0f, 0.0f),
                true);
            tunnelTeleport.setEnabled(false);
        }

		printFinishedTime();

    }

	void World::printFinishedTime(){
		if(!start.hasCollided())
			finish.reset();

		if(start.hasCollided() && finish.hasCollided() && finish.isEnabled()){
			//finish.setEnabled(false);
			if(finishTimer.getElapsedSeconds() > 2)
			  std::cout << "Finished after: " << finishTimer.getElapsedSeconds() << " seconds!" << std::endl;
			lastTime = finishTimer.getElapsedSeconds();
			if(highScore == 200)
				highScore = 199;
			else if(lastTime < highScore)
				highScore = lastTime;
			finish.reset();
			start.reset();
			finishTimer.reset();

		}
	}

	float World::getElapsedSeconds(){
	    return finishTimer.getElapsedSeconds();
	}

	float World::getLastTime(){
		return lastTime;
	}

	float World::getHighScore(){
		return highScore;
	}

	void World::resetHighScore(){
		highScore = 200;
	}
} }
<|endoftext|>


<commit_before>/*

    Musical Tabletop Coding Framework

    Copyright (c) 2012 Carles F. Julià <carles.fernandez@upf.edu>
    Copyright (c) 2010 Daniel Gallardo Grassot <daniel.gallardo@upf.edu>

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

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

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

*/

#pragma once
#include "dispatcher.hpp"
#include "OscTools.hpp"
#include <set>
#include "InputGestureDirectFingers.hpp"

class OscFingerReporter : public Graphic
{

    std::set< DirectFinger * > updatelist;

    public:
    void newCursor(InputGestureDirectFingers::newCursorArgs & a)
    {
        DirectFinger *df = a.finger;
        ofxOscMessage msg;
        msg.setAddress("/finger/in");
        OscPacker(msg) << (int)df->s_id << (float) df->getX() << (float) df->getY();
        OSCDispatcher::Instance().sender.sendMessage(msg);
    }
    void removeCursor(InputGestureDirectFingers::removeCursorArgs & a)
    {
        DirectFinger *df = a.finger;
        ofxOscMessage msg;
        msg.setAddress("/finger/out");
        OscPacker(msg) << (int)df->s_id << (float) df->getX() << (float) df->getY();
        OSCDispatcher::Instance().sender.sendMessage(msg);
    }
    void updateCursor(InputGestureDirectFingers::updateCursorArgs & a)
    {
        DirectFinger *f = a.finger;
        updatelist.insert(f);
    }

    void update()
    {
        for(std::set< DirectFinger * >::iterator it = updatelist.begin(); it != updatelist.end(); ++it)
        {
            DirectFinger *df = *it;
            ofxOscMessage msg;
            msg.setAddress("/finger/move");
            OscPacker(msg) << (int)df->s_id << (float) df->getX() << (float) df->getY();
            OSCDispatcher::Instance().sender.sendMessage(msg);
        }
        updatelist.clear();
    }

    OscFingerReporter()
    {
        this->registerEvent(InputGestureDirectFingers::I().newCursor, &OscFingerReporter::newCursor);
        this->registerEvent(InputGestureDirectFingers::I().removeCursor, &OscFingerReporter::removeCursor);
        this->registerEvent(InputGestureDirectFingers::I().updateCursor, &OscFingerReporter::updateCursor);

    }

};<commit_msg>new addressing in /finger space<commit_after>/*

    Musical Tabletop Coding Framework

    Copyright (c) 2012 Carles F. Julià <carles.fernandez@upf.edu>
    Copyright (c) 2010 Daniel Gallardo Grassot <daniel.gallardo@upf.edu>

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

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

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

*/

#pragma once
#include "dispatcher.hpp"
#include "OscTools.hpp"
#include <set>
#include "InputGestureDirectFingers.hpp"

class OscFingerReporter : public Graphic
{

    std::set< DirectFinger * > updatelist;

    public:
    void newCursor(InputGestureDirectFingers::newCursorArgs & a)
    {
        DirectFinger *df = a.finger;
        ofxOscMessage msg;
        msg.setAddress("/finger");
        OscPacker(msg) << std::string("in") << (int)df->s_id << (float) df->getX() << (float) df->getY();
        OSCDispatcher::Instance().sender.sendMessage(msg);
    }
    void removeCursor(InputGestureDirectFingers::removeCursorArgs & a)
    {
        DirectFinger *df = a.finger;
        ofxOscMessage msg;
        msg.setAddress("/finger");
        OscPacker(msg) << std::string("out") << (int)df->s_id << (float) df->getX() << (float) df->getY();
        OSCDispatcher::Instance().sender.sendMessage(msg);
    }
    void updateCursor(InputGestureDirectFingers::updateCursorArgs & a)
    {
        DirectFinger *f = a.finger;
        updatelist.insert(f);
    }

    void update()
    {
        for(std::set< DirectFinger * >::iterator it = updatelist.begin(); it != updatelist.end(); ++it)
        {
            DirectFinger *df = *it;
            ofxOscMessage msg;
            msg.setAddress("/finger");
            OscPacker(msg) << std::string("move") << (int)df->s_id << (float) df->getX() << (float) df->getY();
            OSCDispatcher::Instance().sender.sendMessage(msg);
        }
        updatelist.clear();
    }

    OscFingerReporter()
    {
        this->registerEvent(InputGestureDirectFingers::I().newCursor, &OscFingerReporter::newCursor);
        this->registerEvent(InputGestureDirectFingers::I().removeCursor, &OscFingerReporter::removeCursor);
        this->registerEvent(InputGestureDirectFingers::I().updateCursor, &OscFingerReporter::updateCursor);

    }

};<|endoftext|>