<commit_before>/*
 * W.J. van der Laan 2011-2012
 */
#include "bitcoingui.h"
#include "clientmodel.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "guiutil.h"
#include "guiconstants.h"

#include "init.h"
#include "ui_interface.h"
#include "qtipcserver.h"

#include <QApplication>
#include <QMessageBox>
#include <QTextCodec>
#include <QLocale>
#include <QTranslator>
#include <QSplashScreen>
#include <QLibraryInfo>

#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
#define _BITCOIN_QT_PLUGINS_INCLUDED
#define __INSURE__
#include <QtPlugin>
Q_IMPORT_PLUGIN(qcncodecs)
Q_IMPORT_PLUGIN(qjpcodecs)
Q_IMPORT_PLUGIN(qtwcodecs)
Q_IMPORT_PLUGIN(qkrcodecs)
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
#endif

// Need a global reference for the notifications to find the GUI
static BitcoinGUI *guiref;
static QSplashScreen *splashref;

static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
{
    // Message from network thread
    if(guiref)
    {
        bool modal = (style & CClientUIInterface::MODAL);
        // in case of modal message, use blocking connection to wait for user to click OK
        QMetaObject::invokeMethod(guiref, "error",
                                   modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
                                   Q_ARG(QString, QString::fromStdString(caption)),
                                   Q_ARG(QString, QString::fromStdString(message)),
                                   Q_ARG(bool, modal));
    }
    else
    {
        printf("%s: %s\n", caption.c_str(), message.c_str());
        fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
    }
}

static bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
{
    if(!guiref)
        return false;
    if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon)
        return true;
    bool payFee = false;

    QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
                               Q_ARG(qint64, nFeeRequired),
                               Q_ARG(bool*, &payFee));

    return payFee;
}

static void ThreadSafeHandleURI(const std::string& strURI)
{
    if(!guiref)
        return;

    QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(),
                               Q_ARG(QString, QString::fromStdString(strURI)));
}

static void InitMessage(const std::string &message)
{
    if(splashref)
    {
        splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(255,255,200));
        QApplication::instance()->processEvents();
    }
}

static void QueueShutdown()
{
    QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
}

/*
   Translate string to current locale using Qt.
 */
static std::string Translate(const char* psz)
{
    return QCoreApplication::translate("bitcoin-core", psz).toStdString();
}

/* Handle runaway exceptions. Shows a message box with the problem and quits the program.
 */
static void handleRunawayException(std::exception *e)
{
    PrintExceptionContinue(e, "Runaway exception");
    QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning));
    exit(1);
}

#ifndef BITCOIN_QT_TEST
int main(int argc, char *argv[])
{
    // Do this early as we don't want to bother initializing if we are just calling IPC
    ipcScanRelay(argc, argv);

    // Internal string conversion is all UTF-8
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());

    Q_INIT_RESOURCE(bitcoin);
    QApplication app(argc, argv);

    // Install global event filter that makes sure that long tooltips can be word-wrapped
    app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));

    // Command-line options take precedence:
    ParseParameters(argc, argv);

    // ... then bitcoin.conf:
    if (!boost::filesystem::is_directory(GetDataDir(false)))
    {
        fprintf(stderr, "Error: Specified directory does not exist\n");
        return 1;
    }
    ReadConfigFile(mapArgs, mapMultiArgs);

    // Application identification (must be set before OptionsModel is initialized,
    // as it is used to locate QSettings)
    app.setOrganizationName("Bitcoin");
    app.setOrganizationDomain("bitcoin.org");
    if(GetBoolArg("-testnet")) // Separate UI settings for testnet
        app.setApplicationName("Bitcoin-Qt-testnet");
    else
        app.setApplicationName("Bitcoin-Qt");

    // ... then GUI settings:
    OptionsModel optionsModel;

    // Get desired locale (e.g. "de_DE") from command line or use system locale
    QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
    QString lang = lang_territory;
    // Convert to "de" only by truncating "_DE"
    lang.truncate(lang_territory.lastIndexOf('_'));

    QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
    // Load language files for configured locale:
    // - First load the translator for the base language, without territory
    // - Then load the more specific locale translator

    // Load e.g. qt_de.qm
    if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
        app.installTranslator(&qtTranslatorBase);

    // Load e.g. qt_de_DE.qm
    if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
        app.installTranslator(&qtTranslator);

    // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
    if (translatorBase.load(lang, ":/translations/"))
        app.installTranslator(&translatorBase);

    // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
    if (translator.load(lang_territory, ":/translations/"))
        app.installTranslator(&translator);

    // Subscribe to global signals from core
    uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
    uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
    uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI);
    uiInterface.InitMessage.connect(InitMessage);
    uiInterface.QueueShutdown.connect(QueueShutdown);
    uiInterface.Translate.connect(Translate);

    // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
    // but before showing splash screen.
    if (mapArgs.count("-?") || mapArgs.count("--help"))
    {
        GUIUtil::HelpMessageBox help;
        help.showOrPrint();
        return 1;
    }

    QSplashScreen splash(QPixmap(":/images/splash"), 0);
    if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
    {
        splash.show();
        splash.setAutoFillBackground(true);
        splashref = &splash;
    }

    app.processEvents();

    app.setQuitOnLastWindowClosed(false);

    try
    {
        // Regenerate startup link, to fix links to old versions
        if (GUIUtil::GetStartOnSystemStartup())
            GUIUtil::SetStartOnSystemStartup(true);

        BitcoinGUI window;
        guiref = &window;
        if(AppInit2())
        {
            {
                // Put this in a block, so that the Model objects are cleaned up before
                // calling Shutdown().

                optionsModel.Upgrade(); // Must be done after AppInit2

                if (splashref)
                    splash.finish(&window);

                ClientModel clientModel(&optionsModel);
                WalletModel walletModel(pwalletMain, &optionsModel);

                window.setClientModel(&clientModel);
                window.setWalletModel(&walletModel);

                // If -min option passed, start window minimized.
                if(GetBoolArg("-min"))
                {
                    window.showMinimized();
                }
                else
                {
                    window.show();
                }

                // Place this here as guiref has to be defined if we don't want to lose URIs
                ipcInit(argc, argv);

                app.exec();

                window.hide();
                window.setClientModel(0);
                window.setWalletModel(0);
                guiref = 0;
            }
            // Shutdown the core and its threads, but don't exit Bitcoin-Qt here
            Shutdown(NULL);
        }
        else
        {
            return 1;
        }
    } catch (std::exception& e) {
        handleRunawayException(&e);
    } catch (...) {
        handleRunawayException(NULL);
    }
    return 0;
}
#endif // BITCOIN_QT_TEST
<commit_msg>When datadir missing, show messagebox instead of printing error to stderr<commit_after>/*
 * W.J. van der Laan 2011-2012
 */
#include "bitcoingui.h"
#include "clientmodel.h"
#include "walletmodel.h"
#include "optionsmodel.h"
#include "guiutil.h"
#include "guiconstants.h"

#include "init.h"
#include "ui_interface.h"
#include "qtipcserver.h"

#include <QApplication>
#include <QMessageBox>
#include <QTextCodec>
#include <QLocale>
#include <QTranslator>
#include <QSplashScreen>
#include <QLibraryInfo>

#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
#define _BITCOIN_QT_PLUGINS_INCLUDED
#define __INSURE__
#include <QtPlugin>
Q_IMPORT_PLUGIN(qcncodecs)
Q_IMPORT_PLUGIN(qjpcodecs)
Q_IMPORT_PLUGIN(qtwcodecs)
Q_IMPORT_PLUGIN(qkrcodecs)
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
#endif

// Need a global reference for the notifications to find the GUI
static BitcoinGUI *guiref;
static QSplashScreen *splashref;

static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
{
    // Message from network thread
    if(guiref)
    {
        bool modal = (style & CClientUIInterface::MODAL);
        // in case of modal message, use blocking connection to wait for user to click OK
        QMetaObject::invokeMethod(guiref, "error",
                                   modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
                                   Q_ARG(QString, QString::fromStdString(caption)),
                                   Q_ARG(QString, QString::fromStdString(message)),
                                   Q_ARG(bool, modal));
    }
    else
    {
        printf("%s: %s\n", caption.c_str(), message.c_str());
        fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
    }
}

static bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
{
    if(!guiref)
        return false;
    if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon)
        return true;
    bool payFee = false;

    QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
                               Q_ARG(qint64, nFeeRequired),
                               Q_ARG(bool*, &payFee));

    return payFee;
}

static void ThreadSafeHandleURI(const std::string& strURI)
{
    if(!guiref)
        return;

    QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(),
                               Q_ARG(QString, QString::fromStdString(strURI)));
}

static void InitMessage(const std::string &message)
{
    if(splashref)
    {
        splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(255,255,200));
        QApplication::instance()->processEvents();
    }
}

static void QueueShutdown()
{
    QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
}

/*
   Translate string to current locale using Qt.
 */
static std::string Translate(const char* psz)
{
    return QCoreApplication::translate("bitcoin-core", psz).toStdString();
}

/* Handle runaway exceptions. Shows a message box with the problem and quits the program.
 */
static void handleRunawayException(std::exception *e)
{
    PrintExceptionContinue(e, "Runaway exception");
    QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Bitcoin can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning));
    exit(1);
}

#ifndef BITCOIN_QT_TEST
int main(int argc, char *argv[])
{
    // Do this early as we don't want to bother initializing if we are just calling IPC
    ipcScanRelay(argc, argv);

    // Internal string conversion is all UTF-8
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());

    Q_INIT_RESOURCE(bitcoin);
    QApplication app(argc, argv);

    // Install global event filter that makes sure that long tooltips can be word-wrapped
    app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));

    // Command-line options take precedence:
    ParseParameters(argc, argv);

    // ... then bitcoin.conf:
    if (!boost::filesystem::is_directory(GetDataDir(false)))
    {
        // This message can not be translated, as translation is not initialized yet
        // (which not yet possible because lang=XX can be overridden in bitcoin.conf in the data directory)
        QMessageBox::critical(0, "Bitcoin",
                              QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
        return 1;
    }
    ReadConfigFile(mapArgs, mapMultiArgs);

    // Application identification (must be set before OptionsModel is initialized,
    // as it is used to locate QSettings)
    app.setOrganizationName("Bitcoin");
    app.setOrganizationDomain("bitcoin.org");
    if(GetBoolArg("-testnet")) // Separate UI settings for testnet
        app.setApplicationName("Bitcoin-Qt-testnet");
    else
        app.setApplicationName("Bitcoin-Qt");

    // ... then GUI settings:
    OptionsModel optionsModel;

    // Get desired locale (e.g. "de_DE") from command line or use system locale
    QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
    QString lang = lang_territory;
    // Convert to "de" only by truncating "_DE"
    lang.truncate(lang_territory.lastIndexOf('_'));

    QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
    // Load language files for configured locale:
    // - First load the translator for the base language, without territory
    // - Then load the more specific locale translator

    // Load e.g. qt_de.qm
    if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
        app.installTranslator(&qtTranslatorBase);

    // Load e.g. qt_de_DE.qm
    if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
        app.installTranslator(&qtTranslator);

    // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
    if (translatorBase.load(lang, ":/translations/"))
        app.installTranslator(&translatorBase);

    // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
    if (translator.load(lang_territory, ":/translations/"))
        app.installTranslator(&translator);

    // Subscribe to global signals from core
    uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
    uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
    uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI);
    uiInterface.InitMessage.connect(InitMessage);
    uiInterface.QueueShutdown.connect(QueueShutdown);
    uiInterface.Translate.connect(Translate);

    // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
    // but before showing splash screen.
    if (mapArgs.count("-?") || mapArgs.count("--help"))
    {
        GUIUtil::HelpMessageBox help;
        help.showOrPrint();
        return 1;
    }

    QSplashScreen splash(QPixmap(":/images/splash"), 0);
    if (GetBoolArg("-splash", true) && !GetBoolArg("-min"))
    {
        splash.show();
        splash.setAutoFillBackground(true);
        splashref = &splash;
    }

    app.processEvents();

    app.setQuitOnLastWindowClosed(false);

    try
    {
        // Regenerate startup link, to fix links to old versions
        if (GUIUtil::GetStartOnSystemStartup())
            GUIUtil::SetStartOnSystemStartup(true);

        BitcoinGUI window;
        guiref = &window;
        if(AppInit2())
        {
            {
                // Put this in a block, so that the Model objects are cleaned up before
                // calling Shutdown().

                optionsModel.Upgrade(); // Must be done after AppInit2

                if (splashref)
                    splash.finish(&window);

                ClientModel clientModel(&optionsModel);
                WalletModel walletModel(pwalletMain, &optionsModel);

                window.setClientModel(&clientModel);
                window.setWalletModel(&walletModel);

                // If -min option passed, start window minimized.
                if(GetBoolArg("-min"))
                {
                    window.showMinimized();
                }
                else
                {
                    window.show();
                }

                // Place this here as guiref has to be defined if we don't want to lose URIs
                ipcInit(argc, argv);

                app.exec();

                window.hide();
                window.setClientModel(0);
                window.setWalletModel(0);
                guiref = 0;
            }
            // Shutdown the core and its threads, but don't exit Bitcoin-Qt here
            Shutdown(NULL);
        }
        else
        {
            return 1;
        }
    } catch (std::exception& e) {
        handleRunawayException(&e);
    } catch (...) {
        handleRunawayException(NULL);
    }
    return 0;
}
#endif // BITCOIN_QT_TEST
<|endoftext|>


<commit_before>#include "res2hutils.hpp"

#include <fstream>

uint32_t calculateAdler32(const unsigned char * data, const size_t dataSize, uint32_t adler)
{
	uint32_t s1 = adler & 0xffff;
	uint32_t s2 = (adler >> 16) & 0xffff;
	//calculate checksum for buffer
	for (std::streamsize n = 0; n < dataSize; n++) {
		s1 = (s1 + data[n]) % 65521;
		s2 = (s2 + s1) % 65521;
	}
	//build final checksum
	return (s2 << 16) + s1;
}

uint32_t calculateAdler32(const std::string & filePath, const size_t dataSize, uint32_t adler)
{
	//open file
	std::ifstream inStream;
	inStream.open(filePath, std::ifstream::in | std::ifstream::binary);
	if (inStream.is_open() && inStream.good()) {
		//loop until EOF or dataSize reached
		std::streamsize rollingSize = 0;
		while (!inStream.eof() && inStream.good()) {
			char buffer[1024];
			std::streamsize readSize = sizeof(buffer);
			try {
				//try reading data from input file
				inStream.read(reinterpret_cast<char *>(&buffer), sizeof(buffer));
			}
			catch (std::ios_base::failure) { /*reading didn't work properly. salvage what we can.*/ }
			//store how many bytes were actually read
			readSize = inStream.gcount();
			//clamp to dataSize
			if (rollingSize + readSize > dataSize) {
				readSize = dataSize - rollingSize;
			}
			//calculate checksum for buffer
			adler = calculateAdler32(buffer, (size_t)readSize, adler);
			//update size already read
			rollingSize += readSize;
			if (rollingSize >= dataSize) {
				break;
			}
		}
		//close file
		inStream.close();
	}
	return adler;
}
<commit_msg>Fix checksum function<commit_after>#include "res2hutils.hpp"

#include <fstream>

uint32_t calculateAdler32(const unsigned char * data, const size_t dataSize, uint32_t adler)
{
	uint32_t s1 = adler & 0xffff;
	uint32_t s2 = (adler >> 16) & 0xffff;
	//calculate checksum for buffer
	for (std::streamsize n = 0; n < dataSize; n++) {
		s1 = (s1 + data[n]) % 65521;
		s2 = (s2 + s1) % 65521;
	}
	//build final checksum
	return (s2 << 16) + s1;
}

uint32_t calculateAdler32(const std::string & filePath, const size_t dataSize, uint32_t adler)
{
	//open file
	std::ifstream inStream;
	inStream.open(filePath, std::ifstream::in | std::ifstream::binary);
	if (inStream.is_open() && inStream.good()) {
		//loop until EOF or dataSize reached
		std::streamsize rollingSize = 0;
		while (!inStream.eof() && inStream.good()) {
			unsigned char buffer[1024];
			std::streamsize readSize = sizeof(buffer);
			try {
				//try reading data from input file
				inStream.read(reinterpret_cast<char *>(&buffer), sizeof(buffer));
			}
			catch (std::ios_base::failure) { /*reading didn't work properly. salvage what we can.*/ }
			//store how many bytes were actually read
			readSize = inStream.gcount();
			//clamp to dataSize if the caller wants to checksum only part of the file
			if (dataSize > 0 && rollingSize + readSize > dataSize) {
				readSize = dataSize - rollingSize;
			}
			//calculate checksum for buffer
			adler = calculateAdler32((const unsigned char*)&buffer, (size_t)readSize, adler);
			//update size already read
			rollingSize += readSize;
			if (dataSize > 0 && rollingSize >= dataSize) {
				break;
			}
		}
		//close file
		inStream.close();
	}
	return adler;
}
<|endoftext|>


<commit_before>/*
 * Launch and manage FastCGI child processes.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Stock.hxx"
#include "Quark.hxx"
#include "stock/MapStock.hxx"
#include "stock/Class.hxx"
#include "stock/Item.hxx"
#include "child_stock.hxx"
#include "child_manager.hxx"
#include "spawn/Prepared.hxx"
#include "spawn/ChildOptions.hxx"
#include "spawn/JailConfig.hxx"
#include "gerrno.h"
#include "pool.hxx"
#include "event/Event.hxx"
#include "event/Callback.hxx"
#include "util/ConstBuffer.hxx"

#include <daemon/log.h>

#include <glib.h>

#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#ifdef __linux
#include <sched.h>
#endif

struct FcgiStock {
    StockMap *hstock;
    StockMap *child_stock;

    void FadeAll() {
        hstock_fade_all(*hstock);
        hstock_fade_all(*child_stock);
    }
};

struct FcgiChildParams {
    const char *executable_path;

    ConstBuffer<const char *> args;

    const ChildOptions *options;

    const char *GetStockKey(struct pool &pool) const;
};

struct FcgiConnection final : PoolStockItem {
    JailParams jail_params;

    struct jail_config jail_config;

    StockItem *child = nullptr;

    int fd = -1;
    Event event;

    /**
     * Is this a fresh connection to the FastCGI child process?
     */
    bool fresh;

    /**
     * Shall the FastCGI child process be killed?
     */
    bool kill;

    /**
     * Was the current request aborted by the fcgi_client caller?
     */
    bool aborted;

    explicit FcgiConnection(struct pool &_pool, CreateStockItem c)
        :PoolStockItem(_pool, c) {}

    gcc_pure
    const char *GetStockKey() const {
        return child_stock_item_key(child);
    }

    void EventCallback(evutil_socket_t fd, short events);

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override;
    bool Release(gcc_unused void *ctx) override;
    void Destroy(void *ctx) override;
};

const char *
FcgiChildParams::GetStockKey(struct pool &pool) const
{
    const char *key = executable_path;

    for (auto i : args)
        key = p_strcat(&pool, key, " ", i, nullptr);

    for (auto i : options->env)
        key = p_strcat(&pool, key, "$", i, nullptr);

    char options_buffer[4096];
    *options->MakeId(options_buffer) = 0;
    if (*options_buffer != 0)
        key = p_strcat(&pool, key, options_buffer, nullptr);

    return key;
}

/*
 * libevent callback
 *
 */

inline void
FcgiConnection::EventCallback(evutil_socket_t _fd, short events)
{
    assert(_fd == fd);

    if ((events & EV_TIMEOUT) == 0) {
        char buffer;
        ssize_t nbytes = recv(_fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
        if (nbytes < 0)
            daemon_log(2, "error on idle FastCGI connection '%s': %s\n",
                       GetStockKey(), strerror(errno));
        else if (nbytes > 0)
            daemon_log(2, "unexpected data from idle FastCGI connection '%s'\n",
                       GetStockKey());
    }

    InvokeIdleDisconnect();
    pool_commit();
}

/*
 * child_stock class
 *
 */

static bool
fcgi_child_stock_prepare(gcc_unused const char *key, void *info, int fd,
                         PreparedChildProcess &p, GError **error_r)
{
    const auto &params = *(const FcgiChildParams *)info;
    const ChildOptions &options = *params.options;

    p.stdin_fd = fd;

    /* the FastCGI protocol defines a channel for stderr, so we could
       close its "real" stderr here, but many FastCGI applications
       don't use the FastCGI protocol to send error messages, so we
       just keep it open */

    int null_fd = open("/dev/null", O_WRONLY|O_CLOEXEC|O_NOCTTY);
    if (null_fd >= 0)
        p.stdout_fd = null_fd;

    p.Append(params.executable_path);
    for (auto i : params.args)
        p.Append(i);

    return options.CopyTo(p, true, nullptr, error_r);
}

static const ChildStockClass fcgi_child_stock_class = {
    .shutdown_signal = SIGUSR1,
    .socket_type = nullptr,
    .prepare = fcgi_child_stock_prepare,
};

/*
 * stock class
 *
 */

static void
fcgi_stock_create(void *ctx, struct pool &parent_pool, CreateStockItem c,
                  const char *key, void *info,
                  gcc_unused struct pool &caller_pool,
                  gcc_unused struct async_operation_ref &async_ref)
{
    FcgiStock *fcgi_stock = (FcgiStock *)ctx;
    FcgiChildParams *params = (FcgiChildParams *)info;

    assert(key != nullptr);
    assert(params != nullptr);
    assert(params->executable_path != nullptr);

    auto &pool = *pool_new_linear(&parent_pool, "fcgi_connection", 2048);
    auto *connection = NewFromPool<FcgiConnection>(pool, pool, c);

    const ChildOptions *const options = params->options;
    if (options->jail.enabled) {
        connection->jail_params.CopyFrom(pool, options->jail);

        if (!jail_config_load(&connection->jail_config,
                              "/etc/cm4all/jailcgi/jail.conf", &pool)) {
            GError *error = g_error_new(fcgi_quark(), 0,
                                        "Failed to load /etc/cm4all/jailcgi/jail.conf");
            connection->InvokeCreateError(error);
            return;
        }
    } else
        connection->jail_params.enabled = false;

    GError *error = nullptr;
    connection->child = hstock_get_now(*fcgi_stock->child_stock, pool,
                                       key, params, &error);
    if (connection->child == nullptr) {
        g_prefix_error(&error, "failed to start to FastCGI server '%s': ",
                       key);
        connection->InvokeCreateError(error);
        return;
    }

    connection->fd = child_stock_item_connect(connection->child, &error);
    if (connection->fd < 0) {
        g_prefix_error(&error, "failed to connect to FastCGI server '%s': ",
                       key);

        connection->kill = true;
        connection->InvokeCreateError(error);
        return;
    }

    connection->fresh = true;
    connection->kill = false;
    connection->aborted = false;

    connection->event.Set(connection->fd, EV_READ|EV_TIMEOUT,
                          MakeEventCallback(FcgiConnection, EventCallback),
                          connection);

    connection->InvokeCreateSuccess();
}

bool
FcgiConnection::Borrow(gcc_unused void *ctx)
{
    /* check the connection status before using it, just in case the
       FastCGI server has decided to close the connection before
       fcgi_connection_event_callback() got invoked */
    char buffer;
    ssize_t nbytes = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
    if (nbytes > 0) {
        daemon_log(2, "unexpected data from idle FastCGI connection '%s'\n",
                   GetStockKey());
        return false;
    } else if (nbytes == 0) {
        /* connection closed (not worth a log message) */
        return false;
    } else if (errno != EAGAIN) {
        daemon_log(2, "error on idle FastCGI connection '%s': %s\n",
                   GetStockKey(), strerror(errno));
        return false;
    }

    event.Delete();
    aborted = false;
    return true;
}

bool
FcgiConnection::Release(gcc_unused void *ctx)
{
    static constexpr struct timeval tv = {
        .tv_sec = 300,
        .tv_usec = 0,
    };

    fresh = false;
    event.Add(tv);
    return true;
}

void
FcgiConnection::Destroy(void *ctx)
{
    FcgiStock *fcgi_stock = (FcgiStock *)ctx;

    if (fd >= 0) {
        event.Delete();
        close(fd);
    }

    if (child != nullptr)
        child_stock_put(fcgi_stock->child_stock, child, kill);

    PoolStockItem::Destroy(ctx);
}

static constexpr StockClass fcgi_stock_class = {
    .create = fcgi_stock_create,
};

/*
 * interface
 *
 */

FcgiStock *
fcgi_stock_new(struct pool *pool, unsigned limit, unsigned max_idle)
{
    auto fcgi_stock = NewFromPool<FcgiStock>(*pool);
    fcgi_stock->child_stock = child_stock_new(pool, limit, max_idle,
                                              &fcgi_child_stock_class);
    fcgi_stock->hstock = hstock_new(*pool, fcgi_stock_class, fcgi_stock,
                                    limit, max_idle);

    return fcgi_stock;
}

void
fcgi_stock_free(FcgiStock *fcgi_stock)
{
    hstock_free(fcgi_stock->hstock);
    hstock_free(fcgi_stock->child_stock);
}

void
fcgi_stock_fade_all(FcgiStock &fs)
{
    fs.FadeAll();
}

StockItem *
fcgi_stock_get(FcgiStock *fcgi_stock, struct pool *pool,
               const ChildOptions &options,
               const char *executable_path,
               ConstBuffer<const char *> args,
               GError **error_r)
{
    auto params = NewFromPool<FcgiChildParams>(*pool);
    params->executable_path = executable_path;
    params->args = args;
    params->options = &options;

    return hstock_get_now(*fcgi_stock->hstock, *pool,
                          params->GetStockKey(*pool), params,
                          error_r);
}

int
fcgi_stock_item_get_domain(gcc_unused const StockItem &item)
{
    return AF_UNIX;
}

int
fcgi_stock_item_get(const StockItem &item)
{
    const auto *connection = (const FcgiConnection *)&item;

    assert(connection->fd >= 0);

    return connection->fd;
}

const char *
fcgi_stock_translate_path(const StockItem &item,
                          const char *path, struct pool *pool)
{
    const auto *connection = (const FcgiConnection *)&item;

    if (!connection->jail_params.enabled)
        /* no JailCGI - application's namespace is the same as ours,
           no translation needed */
        return path;

    const char *jailed = jail_translate_path(&connection->jail_config, path,
                                             connection->jail_params.home_directory,
                                             pool);
    return jailed != nullptr ? jailed : path;
}

void
fcgi_stock_put(FcgiStock *fcgi_stock, StockItem &item,
               bool destroy)
{
    auto *connection = (FcgiConnection *)&item;

    if (connection->fresh && connection->aborted && destroy)
        /* the fcgi_client caller has aborted the request before the
           first response on a fresh connection was received: better
           kill the child process, it may be failing on us
           completely */
        connection->kill = true;

    hstock_put(*fcgi_stock->hstock, connection->GetStockKey(),
               item, destroy);
}

void
fcgi_stock_aborted(StockItem &item)
{
    auto *connection = (FcgiConnection *)&item;

    connection->aborted = true;
}
<commit_msg>fcgi/Stock: pass caller_pool to hstock_get_now()<commit_after>/*
 * Launch and manage FastCGI child processes.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "Stock.hxx"
#include "Quark.hxx"
#include "stock/MapStock.hxx"
#include "stock/Class.hxx"
#include "stock/Item.hxx"
#include "child_stock.hxx"
#include "child_manager.hxx"
#include "spawn/Prepared.hxx"
#include "spawn/ChildOptions.hxx"
#include "spawn/JailConfig.hxx"
#include "gerrno.h"
#include "pool.hxx"
#include "event/Event.hxx"
#include "event/Callback.hxx"
#include "util/ConstBuffer.hxx"

#include <daemon/log.h>

#include <glib.h>

#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#ifdef __linux
#include <sched.h>
#endif

struct FcgiStock {
    StockMap *hstock;
    StockMap *child_stock;

    void FadeAll() {
        hstock_fade_all(*hstock);
        hstock_fade_all(*child_stock);
    }
};

struct FcgiChildParams {
    const char *executable_path;

    ConstBuffer<const char *> args;

    const ChildOptions *options;

    const char *GetStockKey(struct pool &pool) const;
};

struct FcgiConnection final : PoolStockItem {
    JailParams jail_params;

    struct jail_config jail_config;

    StockItem *child = nullptr;

    int fd = -1;
    Event event;

    /**
     * Is this a fresh connection to the FastCGI child process?
     */
    bool fresh;

    /**
     * Shall the FastCGI child process be killed?
     */
    bool kill;

    /**
     * Was the current request aborted by the fcgi_client caller?
     */
    bool aborted;

    explicit FcgiConnection(struct pool &_pool, CreateStockItem c)
        :PoolStockItem(_pool, c) {}

    gcc_pure
    const char *GetStockKey() const {
        return child_stock_item_key(child);
    }

    void EventCallback(evutil_socket_t fd, short events);

    /* virtual methods from class StockItem */
    bool Borrow(gcc_unused void *ctx) override;
    bool Release(gcc_unused void *ctx) override;
    void Destroy(void *ctx) override;
};

const char *
FcgiChildParams::GetStockKey(struct pool &pool) const
{
    const char *key = executable_path;

    for (auto i : args)
        key = p_strcat(&pool, key, " ", i, nullptr);

    for (auto i : options->env)
        key = p_strcat(&pool, key, "$", i, nullptr);

    char options_buffer[4096];
    *options->MakeId(options_buffer) = 0;
    if (*options_buffer != 0)
        key = p_strcat(&pool, key, options_buffer, nullptr);

    return key;
}

/*
 * libevent callback
 *
 */

inline void
FcgiConnection::EventCallback(evutil_socket_t _fd, short events)
{
    assert(_fd == fd);

    if ((events & EV_TIMEOUT) == 0) {
        char buffer;
        ssize_t nbytes = recv(_fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
        if (nbytes < 0)
            daemon_log(2, "error on idle FastCGI connection '%s': %s\n",
                       GetStockKey(), strerror(errno));
        else if (nbytes > 0)
            daemon_log(2, "unexpected data from idle FastCGI connection '%s'\n",
                       GetStockKey());
    }

    InvokeIdleDisconnect();
    pool_commit();
}

/*
 * child_stock class
 *
 */

static bool
fcgi_child_stock_prepare(gcc_unused const char *key, void *info, int fd,
                         PreparedChildProcess &p, GError **error_r)
{
    const auto &params = *(const FcgiChildParams *)info;
    const ChildOptions &options = *params.options;

    p.stdin_fd = fd;

    /* the FastCGI protocol defines a channel for stderr, so we could
       close its "real" stderr here, but many FastCGI applications
       don't use the FastCGI protocol to send error messages, so we
       just keep it open */

    int null_fd = open("/dev/null", O_WRONLY|O_CLOEXEC|O_NOCTTY);
    if (null_fd >= 0)
        p.stdout_fd = null_fd;

    p.Append(params.executable_path);
    for (auto i : params.args)
        p.Append(i);

    return options.CopyTo(p, true, nullptr, error_r);
}

static const ChildStockClass fcgi_child_stock_class = {
    .shutdown_signal = SIGUSR1,
    .socket_type = nullptr,
    .prepare = fcgi_child_stock_prepare,
};

/*
 * stock class
 *
 */

static void
fcgi_stock_create(void *ctx, struct pool &parent_pool, CreateStockItem c,
                  const char *key, void *info,
                  struct pool &caller_pool,
                  gcc_unused struct async_operation_ref &async_ref)
{
    FcgiStock *fcgi_stock = (FcgiStock *)ctx;
    FcgiChildParams *params = (FcgiChildParams *)info;

    assert(key != nullptr);
    assert(params != nullptr);
    assert(params->executable_path != nullptr);

    auto &pool = *pool_new_linear(&parent_pool, "fcgi_connection", 2048);
    auto *connection = NewFromPool<FcgiConnection>(pool, pool, c);

    const ChildOptions *const options = params->options;
    if (options->jail.enabled) {
        connection->jail_params.CopyFrom(pool, options->jail);

        if (!jail_config_load(&connection->jail_config,
                              "/etc/cm4all/jailcgi/jail.conf", &pool)) {
            GError *error = g_error_new(fcgi_quark(), 0,
                                        "Failed to load /etc/cm4all/jailcgi/jail.conf");
            connection->InvokeCreateError(error);
            return;
        }
    } else
        connection->jail_params.enabled = false;

    GError *error = nullptr;
    connection->child = hstock_get_now(*fcgi_stock->child_stock, caller_pool,
                                       key, params, &error);
    if (connection->child == nullptr) {
        g_prefix_error(&error, "failed to start to FastCGI server '%s': ",
                       key);
        connection->InvokeCreateError(error);
        return;
    }

    connection->fd = child_stock_item_connect(connection->child, &error);
    if (connection->fd < 0) {
        g_prefix_error(&error, "failed to connect to FastCGI server '%s': ",
                       key);

        connection->kill = true;
        connection->InvokeCreateError(error);
        return;
    }

    connection->fresh = true;
    connection->kill = false;
    connection->aborted = false;

    connection->event.Set(connection->fd, EV_READ|EV_TIMEOUT,
                          MakeEventCallback(FcgiConnection, EventCallback),
                          connection);

    connection->InvokeCreateSuccess();
}

bool
FcgiConnection::Borrow(gcc_unused void *ctx)
{
    /* check the connection status before using it, just in case the
       FastCGI server has decided to close the connection before
       fcgi_connection_event_callback() got invoked */
    char buffer;
    ssize_t nbytes = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT);
    if (nbytes > 0) {
        daemon_log(2, "unexpected data from idle FastCGI connection '%s'\n",
                   GetStockKey());
        return false;
    } else if (nbytes == 0) {
        /* connection closed (not worth a log message) */
        return false;
    } else if (errno != EAGAIN) {
        daemon_log(2, "error on idle FastCGI connection '%s': %s\n",
                   GetStockKey(), strerror(errno));
        return false;
    }

    event.Delete();
    aborted = false;
    return true;
}

bool
FcgiConnection::Release(gcc_unused void *ctx)
{
    static constexpr struct timeval tv = {
        .tv_sec = 300,
        .tv_usec = 0,
    };

    fresh = false;
    event.Add(tv);
    return true;
}

void
FcgiConnection::Destroy(void *ctx)
{
    FcgiStock *fcgi_stock = (FcgiStock *)ctx;

    if (fd >= 0) {
        event.Delete();
        close(fd);
    }

    if (child != nullptr)
        child_stock_put(fcgi_stock->child_stock, child, kill);

    PoolStockItem::Destroy(ctx);
}

static constexpr StockClass fcgi_stock_class = {
    .create = fcgi_stock_create,
};

/*
 * interface
 *
 */

FcgiStock *
fcgi_stock_new(struct pool *pool, unsigned limit, unsigned max_idle)
{
    auto fcgi_stock = NewFromPool<FcgiStock>(*pool);
    fcgi_stock->child_stock = child_stock_new(pool, limit, max_idle,
                                              &fcgi_child_stock_class);
    fcgi_stock->hstock = hstock_new(*pool, fcgi_stock_class, fcgi_stock,
                                    limit, max_idle);

    return fcgi_stock;
}

void
fcgi_stock_free(FcgiStock *fcgi_stock)
{
    hstock_free(fcgi_stock->hstock);
    hstock_free(fcgi_stock->child_stock);
}

void
fcgi_stock_fade_all(FcgiStock &fs)
{
    fs.FadeAll();
}

StockItem *
fcgi_stock_get(FcgiStock *fcgi_stock, struct pool *pool,
               const ChildOptions &options,
               const char *executable_path,
               ConstBuffer<const char *> args,
               GError **error_r)
{
    auto params = NewFromPool<FcgiChildParams>(*pool);
    params->executable_path = executable_path;
    params->args = args;
    params->options = &options;

    return hstock_get_now(*fcgi_stock->hstock, *pool,
                          params->GetStockKey(*pool), params,
                          error_r);
}

int
fcgi_stock_item_get_domain(gcc_unused const StockItem &item)
{
    return AF_UNIX;
}

int
fcgi_stock_item_get(const StockItem &item)
{
    const auto *connection = (const FcgiConnection *)&item;

    assert(connection->fd >= 0);

    return connection->fd;
}

const char *
fcgi_stock_translate_path(const StockItem &item,
                          const char *path, struct pool *pool)
{
    const auto *connection = (const FcgiConnection *)&item;

    if (!connection->jail_params.enabled)
        /* no JailCGI - application's namespace is the same as ours,
           no translation needed */
        return path;

    const char *jailed = jail_translate_path(&connection->jail_config, path,
                                             connection->jail_params.home_directory,
                                             pool);
    return jailed != nullptr ? jailed : path;
}

void
fcgi_stock_put(FcgiStock *fcgi_stock, StockItem &item,
               bool destroy)
{
    auto *connection = (FcgiConnection *)&item;

    if (connection->fresh && connection->aborted && destroy)
        /* the fcgi_client caller has aborted the request before the
           first response on a fresh connection was received: better
           kill the child process, it may be failing on us
           completely */
        connection->kill = true;

    hstock_put(*fcgi_stock->hstock, connection->GetStockKey(),
               item, destroy);
}

void
fcgi_stock_aborted(StockItem &item)
{
    auto *connection = (FcgiConnection *)&item;

    connection->aborted = true;
}
<|endoftext|>


<commit_before>// Rust garbage collection.

#include <utility>
#include <stdint.h>

#include "rust_gc.h"
#include "rust_internal.h"

#ifdef __WIN32__
#include <windows.h>
#else
#include <dlfcn.h>
#endif

namespace gc {

struct root {
    intptr_t frame_offset;
    uintptr_t dynamic;  // 0 = static, 1 = dynamic
    type_desc *tydesc;
};

struct safe_point {
    uintptr_t n_roots;
    root roots[0];
};

class safe_point_map {
    uintptr_t n_safe_points;
    const std::pair<void *,const safe_point *> *index;
    const safe_point *safe_points;

public:
    safe_point_map() {
        const uintptr_t *data = get_safe_point_data();
        n_safe_points = *data++;
        index = (const std::pair<void *,const safe_point *> *)data;
        data += n_safe_points * 2;
        safe_points = (const safe_point *)data;
    }

    static const uintptr_t *get_safe_point_data() {
        static bool init = false;
        static const uintptr_t *data;
        if (!init) {
#ifdef __WIN32__
            data = (const uintptr_t *)GetProcAddress(GetModuleHandle(NULL),
                                                     "rust_gc_safe_points");
#else
            data = (const uintptr_t *)dlsym(RTLD_DEFAULT,
                                            "rust_gc_safe_points");
#endif
            init = true;
        }
        return data;
    }
};

void
gc(rust_task *task) {
    safe_point_map map;

    // TODO
}

void
maybe_gc(rust_task *task) {
    if (safe_point_map::get_safe_point_data() == NULL)
        return;

    // FIXME: We ought to lock this.
    static int zeal = -1;
    if (zeal == -1) {
        char *ev = getenv("RUST_GC_ZEAL");
        zeal = ev && ev[0] != '\0' && ev[0] != '0';
    }

    if (zeal)
        gc(task);
}

}

<commit_msg>rt: Attempt to put out burning tinderbox by fully qualifying gc::gc().<commit_after>// Rust garbage collection.

#include <utility>
#include <stdint.h>

#include "rust_gc.h"
#include "rust_internal.h"

#ifdef __WIN32__
#include <windows.h>
#else
#include <dlfcn.h>
#endif

namespace gc {

struct root {
    intptr_t frame_offset;
    uintptr_t dynamic;  // 0 = static, 1 = dynamic
    type_desc *tydesc;
};

struct safe_point {
    uintptr_t n_roots;
    root roots[0];
};

class safe_point_map {
    uintptr_t n_safe_points;
    const std::pair<void *,const safe_point *> *index;
    const safe_point *safe_points;

public:
    safe_point_map() {
        const uintptr_t *data = get_safe_point_data();
        n_safe_points = *data++;
        index = (const std::pair<void *,const safe_point *> *)data;
        data += n_safe_points * 2;
        safe_points = (const safe_point *)data;
    }

    static const uintptr_t *get_safe_point_data() {
        static bool init = false;
        static const uintptr_t *data;
        if (!init) {
#ifdef __WIN32__
            data = (const uintptr_t *)GetProcAddress(GetModuleHandle(NULL),
                                                     "rust_gc_safe_points");
#else
            data = (const uintptr_t *)dlsym(RTLD_DEFAULT,
                                            "rust_gc_safe_points");
#endif
            init = true;
        }
        return data;
    }
};

void
gc(rust_task *task) {
    safe_point_map map;

    // TODO
}

void
maybe_gc(rust_task *task) {
    if (safe_point_map::get_safe_point_data() == NULL)
        return;

    // FIXME: We ought to lock this.
    static int zeal = -1;
    if (zeal == -1) {
        char *ev = getenv("RUST_GC_ZEAL");
        zeal = ev && ev[0] != '\0' && ev[0] != '0';
    }

    if (zeal)
        gc::gc(task);
}

}

<|endoftext|>


<commit_before>// Copyright (C) 2014 The Regents of the University of California (Regents).
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//
//     * Neither the name of The Regents or University of California nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please contact the author of this library if you have any questions.
// Author: Chris Sweeney (cmsweeney@cs.ucsb.edu)

#include <Eigen/Core>
#include <glog/logging.h>
#include <gflags/gflags.h>
#include <theia/theia.h>
#include <string>
#include <vector>

#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#ifdef FREEGLUT
#include <GL/freeglut.h>
#else
#include <GLUT/glut.h>
#endif
#else
#ifdef _WIN32
#include <windows.h>
#endif
#define GL_GLEXT_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#endif

DEFINE_string(reconstruction, "", "Reconstruction file to be viewed.");

// Containers for the data.
std::vector<theia::Camera> cameras;
std::vector<Eigen::Vector3d> world_points;
std::vector<int> num_views_for_track;

// Parameters for OpenGL.
int mouse_down_x[3], mouse_down_y[3];
float rot_x = 0.0f, rot_y = 0.0f;
float prev_x, prev_y;
float distance = 100.0;
Eigen::Vector3d origin = Eigen::Vector3d::Zero();
bool mouse_rotates = false, mouse_moves = false;
bool draw_cameras = true;
bool draw_axes = false;

float point_size = 1.0;
float normalized_focal_length = 1.0;
int min_num_views_for_track = 2;
void GetPerspectiveParams(double* aspect_ratio, double* fovy) {
  int width = 800;
  int height = 600;
  double focal_length = 600.0;
  *aspect_ratio = static_cast<double>(width) / static_cast<double>(height);
  *fovy = 2 * atan(height / (2.0 * focal_length)) * 180.0 / M_PI;
}

void ChangeSize(int w, int h) {
  // Prevent a divide by zero, when window is too short
  // (you cant make a window of zero width).
  if (h == 0) h = 1;

  // Use the Projection Matrix
  glMatrixMode(GL_PROJECTION);

  // Reset Matrix
  glLoadIdentity();

  // Set the viewport to be the entire window
  double aspect_ratio, fovy;
  GetPerspectiveParams(&aspect_ratio, &fovy);
  glViewport(0, 0, w, h);

  // Set the correct perspective.
  gluPerspective(fovy, aspect_ratio, 0.01f, 100000.0f);

  // Get Back to the Reconstructionview
  glMatrixMode(GL_MODELVIEW);
}

void DrawAxes(float length) {
  glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);

  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  glDisable(GL_LIGHTING);

  glBegin(GL_LINES);
  glColor3f(1.0, 0.0, 0.0);
  glVertex3f(0, 0, 0);
  glVertex3f(length, 0, 0);

  glColor3f(0.0, 1.0, 0.0);
  glVertex3f(0, 0, 0);
  glVertex3f(0, length, 0);

  glColor3f(0.0, 0.0, 1.0);
  glVertex3f(0, 0, 0);
  glVertex3f(0, 0, length);
  glEnd();

  glPopAttrib();
}

void DrawCamera(const theia::Camera& camera) {
  glPushMatrix();
  Eigen::Matrix4d transformation_matrix;
  transformation_matrix.block<3, 3>(0, 0) =
      camera.GetOrientationAsRotationMatrix().transpose();
  transformation_matrix.col(3).head<3>() = camera.GetPosition();
  transformation_matrix(3, 3) = 1.0;

  // Apply world pose transformation.
  glMultMatrixd(reinterpret_cast<GLdouble*>(transformation_matrix.data()));

  // Draw Cameras.
  glColor3f(1.0, 0.0, 0.0);

  // Create the camera wireframe. If intrinsic parameters are not set then use
  // the focal length as a guess.
  const double principal_point_x = (camera.PrincipalPointX() == 0)
                                       ? 0.6 * camera.FocalLength()
                                       : camera.PrincipalPointX();
  const double principal_point_y = (camera.PrincipalPointY() == 0)
                                       ? 0.6 * camera.FocalLength()
                                       : camera.PrincipalPointY();
  const double image_width =
      (camera.ImageWidth() == 0) ? 2 * principal_point_x : camera.ImageWidth();
  const double image_height = (camera.ImageHeight() == 0)
                                  ? 2 * principal_point_y
                                  : camera.ImageHeight();

  // Use the camera calibration to display the cameras.
  Eigen::Matrix3d calibration_matrix;
  camera.GetCalibrationMatrix(&calibration_matrix);
  const Eigen::Matrix3d inv_calibration = calibration_matrix.inverse();
  const Eigen::Vector3d top_left =
      normalized_focal_length * (inv_calibration * Eigen::Vector3d(0, 0, 1));
  const Eigen::Vector3d top_right =
      normalized_focal_length *
      (inv_calibration * Eigen::Vector3d(image_width, 0, 1));
  const Eigen::Vector3d bottom_right =
      normalized_focal_length *
      (inv_calibration * Eigen::Vector3d(image_width, image_height, 1));
  const Eigen::Vector3d bottom_left =
      normalized_focal_length *
      (inv_calibration * Eigen::Vector3d(0, image_height, 1));

  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  glBegin(GL_TRIANGLE_FAN);
  glVertex3f(0.0, 0.0, 0.0);
  glVertex3f(top_right[0], top_right[1], top_right[2]);
  glVertex3f(top_left[0], top_left[1], top_left[2]);
  glVertex3f(bottom_left[0], bottom_left[1], bottom_left[2]);
  glVertex3f(bottom_right[0], bottom_right[1], bottom_right[2]);
  glVertex3f(top_right[0], top_right[1], top_right[2]);
  glEnd();
  glPopMatrix();
}

void RenderScene() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef(-origin[0], -origin[1], -distance);
  glRotatef(180.0f + rot_x, 1.0f, 0.0f, 0.0f);
  glRotatef(-rot_y, 0.0f, 1.0f, 0.0f);
  glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

  if (draw_axes) {
    DrawAxes(1.0);
  }

  // Plot the point cloud.
  glDisable(GL_LIGHTING);
  glEnable(GL_MULTISAMPLE);
  glEnable(GL_BLEND);
  glEnable(GL_POINT_SMOOTH);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  glPointSize(point_size);

  // the coordinates for calculating point attenuation:
  GLfloat point_size_coords[3];
  point_size_coords[0] = 1.0f;
  point_size_coords[1] = 0.055f;
  point_size_coords[2] = 0.0f;
  glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, point_size_coords);

  // Draw the points.
  glColor3f(0.01, 0.01, 0.01);
  glBegin(GL_POINTS);
  for (int i = 0; i < world_points.size(); i++) {
    if (num_views_for_track[i] < min_num_views_for_track) {
      continue;
    }
    glVertex3d(world_points[i].x(), world_points[i].y(), world_points[i].z());
  }
  glEnd();

  // Draw the cameras.
  if (draw_cameras) {
    for (int i = 0; i < cameras.size(); i++) {
      DrawCamera(cameras[i]);
    }
  }
  glutSwapBuffers();
}

void MouseButton(int button, int state, int x, int y) {
  // button down: save coordinates
  if (state == GLUT_DOWN && button <= 2) {
    mouse_down_x[button] = x;
    mouse_down_y[button] = y;
    prev_x = x;
    prev_y = y;

    if (button == GLUT_RIGHT_BUTTON) {
      mouse_rotates = true;
    } else if (button == GLUT_LEFT_BUTTON) {
      mouse_moves = true;
    }
    return;
  }

  if (state == GLUT_UP && button == GLUT_RIGHT_BUTTON) {
    mouse_rotates = false;
  }

  if (state == GLUT_UP && button == GLUT_LEFT_BUTTON) {
    mouse_moves = false;
  }

  // scroll event - wheel reports as button 3 (scroll up) and button 4 (scroll
  // down)
  if ((button == 3) || (button == 4)) {
    // Each wheel event reports like a button click, GLUT_DOWN then GLUT_UP
    if (state == GLUT_UP) return;  // Disregard redundant GLUT_UP events
    if (button == 3)
      distance /= 1.5f;
    else
      distance *= 1.5f;
  }
}

void MouseMove(int x, int y) {
  if (mouse_rotates) {
    const double rotate_factor = 0.5f;
    // notice x & y difference (i.e., changes in x are to rotate about y-axis)
    rot_x -= rotate_factor * (y - prev_y);
    rot_y -= rotate_factor * (x - prev_x);
    prev_x = x;
    prev_y = y;
  } else if (mouse_moves) {
    const double mouse_factor = 0.03f;
    origin.x() -= mouse_factor * (x - prev_x);
    origin.y() += mouse_factor * (y - prev_y);
    prev_x = x;
    prev_y = y;
  }
}

void Keyboard(unsigned char key, int x, int y) {
  switch (key) {
    case 'r':  // reset viewpoint
      distance = 100.0f;
      rot_x = 0.0f;
      rot_y = 0.0f;
      point_size = 1.0;
      origin = Eigen::Vector3d::Zero();
      break;
    case 'z':
      distance /= 1.2f;
      break;
    case 'Z':
      distance *= 1.2f;
      break;
    case 'p':
      point_size /= 1.2;
      break;
    case 'P':
      point_size *= 1.2;
      break;
    case 'f':
      normalized_focal_length /= 1.2;
      break;
    case 'F':
      normalized_focal_length *= 1.2;
      break;
    case 'c':
      draw_cameras = !draw_cameras;
      break;
    case 'a':
      draw_axes = !draw_axes;
      break;
    case 't':
      ++min_num_views_for_track;
      break;
    case 'T':
      --min_num_views_for_track;
      break;
  }
}

// initialize viewport etc.
void Init() {
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  double aspect_ratio, fovy;  // set the correct perspective.
  GetPerspectiveParams(&aspect_ratio, &fovy);
  gluPerspective(fovy, 1.0, .01, 100000.0);

  glMatrixMode(GL_MODELVIEW);
}

void CenterReconstruction() {
  Eigen::Vector3d mean_camera = Eigen::Vector3d::Zero();
  for (int i = 0; i < cameras.size(); i++) {
    mean_camera += cameras[i].GetPosition();
  }
  mean_camera /= static_cast<double>(cameras.size());

  for (int i = 0; i < cameras.size(); i++) {
    const Eigen::Vector3d old_position = cameras[i].GetPosition();
    cameras[i].SetPosition(old_position - mean_camera);
  }
  for (int i = 0; i < world_points.size(); i++) {
    world_points[i] -= mean_camera;
  }
}

int main(int argc, char* argv[]) {
  THEIA_GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  // Output as a binary file.
  std::unique_ptr<theia::Reconstruction> reconstruction(
      new theia::Reconstruction());
  CHECK(ReadReconstruction(FLAGS_reconstruction, reconstruction.get()))
      << "Could not read reconstruction file.";

  // Set up camera drawing.
  cameras.reserve(reconstruction->NumViews());
  for (const theia::ViewId view_id : reconstruction->ViewIds()) {
    const auto* view = reconstruction->View(view_id);
    if (view == nullptr || !view->IsEstimated()) {
      continue;
    }
    cameras.emplace_back(view->Camera());
  }

  // Set up world points.
  world_points.reserve(reconstruction->NumTracks());
  for (const theia::TrackId track_id : reconstruction->TrackIds()) {
    const auto* track = reconstruction->Track(track_id);
    if (track == nullptr || !track->IsEstimated()) {
      continue;
    }
    world_points.emplace_back(track->Point().hnormalized());
    num_views_for_track.emplace_back(track->NumViews());
  }

  CenterReconstruction();

  reconstruction.release();

  // Set up opengl and glut.
  glutInit(&argc, argv);
  glutInitWindowPosition(600, 600);
  glutInitWindowSize(1200, 800);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow("Theia Reconstruction Viewer");

  // Set the camera
  gluLookAt(0.0f, 0.0f, -6.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

  // register callbacks
  glutDisplayFunc(RenderScene);
  glutReshapeFunc(ChangeSize);
  glutMouseFunc(MouseButton);
  glutMotionFunc(MouseMove);
  glutKeyboardFunc(Keyboard);
  glutIdleFunc(RenderScene);

  // enter GLUT event processing loop
  glutMainLoop();

  return 0;
}
<commit_msg>Better display of camera wireframe<commit_after>// Copyright (C) 2014 The Regents of the University of California (Regents).
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//
//     * Neither the name of The Regents or University of California nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please contact the author of this library if you have any questions.
// Author: Chris Sweeney (cmsweeney@cs.ucsb.edu)

#include <Eigen/Core>
#include <glog/logging.h>
#include <gflags/gflags.h>
#include <theia/theia.h>
#include <string>
#include <vector>

#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#ifdef FREEGLUT
#include <GL/freeglut.h>
#else
#include <GLUT/glut.h>
#endif
#else
#ifdef _WIN32
#include <windows.h>
#endif
#define GL_GLEXT_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#endif

DEFINE_string(reconstruction, "", "Reconstruction file to be viewed.");

// Containers for the data.
std::vector<theia::Camera> cameras;
std::vector<Eigen::Vector3d> world_points;
std::vector<int> num_views_for_track;

// Parameters for OpenGL.
int mouse_down_x[3], mouse_down_y[3];
float rot_x = 0.0f, rot_y = 0.0f;
float prev_x, prev_y;
float distance = 100.0;
Eigen::Vector3d origin = Eigen::Vector3d::Zero();
bool mouse_rotates = false, mouse_moves = false;
bool draw_cameras = true;
bool draw_axes = false;

float point_size = 1.0;
float normalized_focal_length = 1.0;
int min_num_views_for_track = 2;
void GetPerspectiveParams(double* aspect_ratio, double* fovy) {
  int width = 800;
  int height = 600;
  double focal_length = 600.0;
  *aspect_ratio = static_cast<double>(width) / static_cast<double>(height);
  *fovy = 2 * atan(height / (2.0 * focal_length)) * 180.0 / M_PI;
}

void ChangeSize(int w, int h) {
  // Prevent a divide by zero, when window is too short
  // (you cant make a window of zero width).
  if (h == 0) h = 1;

  // Use the Projection Matrix
  glMatrixMode(GL_PROJECTION);

  // Reset Matrix
  glLoadIdentity();

  // Set the viewport to be the entire window
  double aspect_ratio, fovy;
  GetPerspectiveParams(&aspect_ratio, &fovy);
  glViewport(0, 0, w, h);

  // Set the correct perspective.
  gluPerspective(fovy, aspect_ratio, 0.01f, 100000.0f);

  // Get Back to the Reconstructionview
  glMatrixMode(GL_MODELVIEW);
}

void DrawAxes(float length) {
  glPushAttrib(GL_POLYGON_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);

  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  glDisable(GL_LIGHTING);

  glBegin(GL_LINES);
  glColor3f(1.0, 0.0, 0.0);
  glVertex3f(0, 0, 0);
  glVertex3f(length, 0, 0);

  glColor3f(0.0, 1.0, 0.0);
  glVertex3f(0, 0, 0);
  glVertex3f(0, length, 0);

  glColor3f(0.0, 0.0, 1.0);
  glVertex3f(0, 0, 0);
  glVertex3f(0, 0, length);
  glEnd();

  glPopAttrib();
}

void DrawCamera(const theia::Camera& camera) {
  glPushMatrix();
  Eigen::Matrix4d transformation_matrix;
  transformation_matrix.block<3, 3>(0, 0) =
      camera.GetOrientationAsRotationMatrix().transpose();
  transformation_matrix.col(3).head<3>() = camera.GetPosition();
  transformation_matrix(3, 3) = 1.0;

  // Apply world pose transformation.
  glMultMatrixd(reinterpret_cast<GLdouble*>(transformation_matrix.data()));

  // Draw Cameras.
  glColor3f(1.0, 0.0, 0.0);

  // Create the camera wireframe. If intrinsic parameters are not set then use
  // the focal length as a guess.

  // Use the camera calibration to display the cameras.
  Eigen::Matrix3d calibration;
  camera.GetCalibrationMatrix(&calibration);
  calibration /= camera.FocalLength();
  calibration(2, 2) = 1.0;

  const Eigen::Vector3d top_left =
      normalized_focal_length * (calibration * Eigen::Vector3d(-1, -1, 1));
  const Eigen::Vector3d top_right =
      normalized_focal_length * (calibration * Eigen::Vector3d(1, -1, 1));
  const Eigen::Vector3d bottom_right =
      normalized_focal_length * (calibration * Eigen::Vector3d(1, 1, 1));
  const Eigen::Vector3d bottom_left =
      normalized_focal_length * (calibration * Eigen::Vector3d(-1, 1, 1));

  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  glBegin(GL_TRIANGLE_FAN);
  glVertex3f(0.0, 0.0, 0.0);
  glVertex3f(top_right[0], top_right[1], top_right[2]);
  glVertex3f(top_left[0], top_left[1], top_left[2]);
  glVertex3f(bottom_left[0], bottom_left[1], bottom_left[2]);
  glVertex3f(bottom_right[0], bottom_right[1], bottom_right[2]);
  glVertex3f(top_right[0], top_right[1], top_right[2]);
  glEnd();
  glPopMatrix();
}

void RenderScene() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef(-origin[0], -origin[1], -distance);
  glRotatef(180.0f + rot_x, 1.0f, 0.0f, 0.0f);
  glRotatef(-rot_y, 0.0f, 1.0f, 0.0f);
  glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

  if (draw_axes) {
    DrawAxes(1.0);
  }

  // Plot the point cloud.
  glDisable(GL_LIGHTING);
  glEnable(GL_MULTISAMPLE);
  glEnable(GL_BLEND);
  glEnable(GL_POINT_SMOOTH);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  glPointSize(point_size);

  // the coordinates for calculating point attenuation:
  GLfloat point_size_coords[3];
  point_size_coords[0] = 1.0f;
  point_size_coords[1] = 0.055f;
  point_size_coords[2] = 0.0f;
  glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, point_size_coords);

  // Draw the points.
  glColor3f(0.01, 0.01, 0.01);
  glBegin(GL_POINTS);
  for (int i = 0; i < world_points.size(); i++) {
    if (num_views_for_track[i] < min_num_views_for_track) {
      continue;
    }
    glVertex3d(world_points[i].x(), world_points[i].y(), world_points[i].z());
  }
  glEnd();

  // Draw the cameras.
  if (draw_cameras) {
    for (int i = 0; i < cameras.size(); i++) {
      DrawCamera(cameras[i]);
    }
  }
  glutSwapBuffers();
}

void MouseButton(int button, int state, int x, int y) {
  // button down: save coordinates
  if (state == GLUT_DOWN && button <= 2) {
    mouse_down_x[button] = x;
    mouse_down_y[button] = y;
    prev_x = x;
    prev_y = y;

    if (button == GLUT_RIGHT_BUTTON) {
      mouse_rotates = true;
    } else if (button == GLUT_LEFT_BUTTON) {
      mouse_moves = true;
    }
    return;
  }

  if (state == GLUT_UP && button == GLUT_RIGHT_BUTTON) {
    mouse_rotates = false;
  }

  if (state == GLUT_UP && button == GLUT_LEFT_BUTTON) {
    mouse_moves = false;
  }

  // scroll event - wheel reports as button 3 (scroll up) and button 4 (scroll
  // down)
  if ((button == 3) || (button == 4)) {
    // Each wheel event reports like a button click, GLUT_DOWN then GLUT_UP
    if (state == GLUT_UP) return;  // Disregard redundant GLUT_UP events
    if (button == 3)
      distance /= 1.5f;
    else
      distance *= 1.5f;
  }
}

void MouseMove(int x, int y) {
  if (mouse_rotates) {
    const double rotate_factor = 0.5f;
    // notice x & y difference (i.e., changes in x are to rotate about y-axis)
    rot_x -= rotate_factor * (y - prev_y);
    rot_y -= rotate_factor * (x - prev_x);
    prev_x = x;
    prev_y = y;
  } else if (mouse_moves) {
    const double mouse_factor = 0.03f;
    origin.x() -= mouse_factor * (x - prev_x);
    origin.y() += mouse_factor * (y - prev_y);
    prev_x = x;
    prev_y = y;
  }
}

void Keyboard(unsigned char key, int x, int y) {
  switch (key) {
    case 'r':  // reset viewpoint
      distance = 100.0f;
      rot_x = 0.0f;
      rot_y = 0.0f;
      point_size = 1.0;
      origin = Eigen::Vector3d::Zero();
      break;
    case 'z':
      distance /= 1.2f;
      break;
    case 'Z':
      distance *= 1.2f;
      break;
    case 'p':
      point_size /= 1.2;
      break;
    case 'P':
      point_size *= 1.2;
      break;
    case 'f':
      normalized_focal_length /= 1.2;
      break;
    case 'F':
      normalized_focal_length *= 1.2;
      break;
    case 'c':
      draw_cameras = !draw_cameras;
      break;
    case 'a':
      draw_axes = !draw_axes;
      break;
    case 't':
      ++min_num_views_for_track;
      break;
    case 'T':
      --min_num_views_for_track;
      break;
  }
}

// initialize viewport etc.
void Init() {
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  double aspect_ratio, fovy;  // set the correct perspective.
  GetPerspectiveParams(&aspect_ratio, &fovy);
  gluPerspective(fovy, 1.0, .01, 100000.0);

  glMatrixMode(GL_MODELVIEW);
}

void CenterReconstruction() {
  Eigen::Vector3d mean_camera = Eigen::Vector3d::Zero();
  for (int i = 0; i < cameras.size(); i++) {
    mean_camera += cameras[i].GetPosition();
  }
  mean_camera /= static_cast<double>(cameras.size());

  for (int i = 0; i < cameras.size(); i++) {
    const Eigen::Vector3d old_position = cameras[i].GetPosition();
    cameras[i].SetPosition(old_position - mean_camera);
  }
  for (int i = 0; i < world_points.size(); i++) {
    world_points[i] -= mean_camera;
  }
}

int main(int argc, char* argv[]) {
  THEIA_GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);

  // Output as a binary file.
  std::unique_ptr<theia::Reconstruction> reconstruction(
      new theia::Reconstruction());
  CHECK(ReadReconstruction(FLAGS_reconstruction, reconstruction.get()))
      << "Could not read reconstruction file.";

  // Set up camera drawing.
  cameras.reserve(reconstruction->NumViews());
  for (const theia::ViewId view_id : reconstruction->ViewIds()) {
    const auto* view = reconstruction->View(view_id);
    if (view == nullptr || !view->IsEstimated()) {
      continue;
    }
    cameras.emplace_back(view->Camera());
  }

  // Set up world points.
  world_points.reserve(reconstruction->NumTracks());
  for (const theia::TrackId track_id : reconstruction->TrackIds()) {
    const auto* track = reconstruction->Track(track_id);
    if (track == nullptr || !track->IsEstimated()) {
      continue;
    }
    world_points.emplace_back(track->Point().hnormalized());
    num_views_for_track.emplace_back(track->NumViews());
  }

  CenterReconstruction();

  reconstruction.release();

  // Set up opengl and glut.
  glutInit(&argc, argv);
  glutInitWindowPosition(600, 600);
  glutInitWindowSize(1200, 800);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow("Theia Reconstruction Viewer");

  // Set the camera
  gluLookAt(0.0f, 0.0f, -6.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

  // register callbacks
  glutDisplayFunc(RenderScene);
  glutReshapeFunc(ChangeSize);
  glutMouseFunc(MouseButton);
  glutMotionFunc(MouseMove);
  glutKeyboardFunc(Keyboard);
  glutIdleFunc(RenderScene);

  // enter GLUT event processing loop
  glutMainLoop();

  return 0;
}
<|endoftext|>


<commit_before>/*
  Name:             xstring
  Copyright:        Copyright (C) 2003-2017 SIL International.
  Documentation:
  Description:
  Create Date:      27 Aug 2012

  Modified Date:    27 Aug 2012
  Authors:          mcdurdin
  Related Files:
  Dependencies:

  Bugs:
  Todo:
  Notes:
  History:          27 Aug 2012 - mcdurdin - I3439 - V9.0 - Refactor xstring support in C++ code
*/
#include "pch.h"

/*
*	int xstrlen( LPBYTE p );
*
*	Parameters:	p	Pointer to string to get length of
*
*	Returns:    length of string
*
*   Called by:  various functions
*
*	xstrlen calculates the length of a string, ignoring some special chars.
*/

PWSTR incxstr(PWSTR p)
{
	if(*p == 0) return p;
	if(*p != UC_SENTINEL)
	{
		if(*p >= 0xD800 && *p <= 0xDBFF && *(p+1) >= 0xDC00 && *(p+1) <= 0xDFFF) return p+2;
		return p+1;
	}

	p+=2;
	switch(*(p-1))
	{
		case CODE_ANY:			return p+1;
		case CODE_NOTANY:   return p+1;
		case CODE_INDEX:		return p+2;
		case CODE_USE:			return p+1;
		case CODE_DEADKEY:		return p+1;
		case CODE_EXTENDED:		p += 2; while(*p != UC_SENTINEL_EXTENDEDEND) p++; return p+1;
		case CODE_CLEARCONTEXT: return p+1;
		case CODE_CALL:			return p+1;
		case CODE_CONTEXTEX:	return p+1;
    case CODE_IFOPT:    return p+3;
    case CODE_IFSYSTEMSTORE: return p+3;
    case CODE_SETOPT:   return p+2;
    case CODE_SETSYSTEMSTORE: return p+2;
    case CODE_RESETOPT: return p+1;
    case CODE_SAVEOPT:  return p+1;
		default:				return p;
	}
}

PWSTR decxstr(PWSTR p, PWSTR pStart)
{
  if (p <= pStart) {
    assert("Attempted to move prior to start of string");
    return NULL;
  }

  p--;
	if(*p == UC_SENTINEL_EXTENDEDEND)
	{
		int n = 0;
		while(*p != UC_SENTINEL && n < 10) { p--; n++; }

    if (p < pStart) {
      // May be a malformed virtual key
      return pStart;
    }
    return p;
	}

  if (p == pStart) return p; // Don't allow test before pStart

  if(*p >= 0xDC00 && *p <= 0xDFFF && *(p-1) >= 0xD800 && *(p-1) <= 0xDBFF)
	{
		return p-1;
	}
	else if(*(p-1) == UC_SENTINEL) return p-1;
	else if(p > pStart + 1 && *(p-2) == UC_SENTINEL)
	{
		switch(*(p-1))
		{
			case CODE_ANY:
			case CODE_NOTANY:
			case CODE_USE:
			case CODE_DEADKEY:
			case CODE_CLEARCONTEXT:
			case CODE_CALL:
			case CODE_CONTEXTEX:
      case CODE_RESETOPT:
      case CODE_SAVEOPT:
        return p-2;
		}
	}
	else if(p > pStart + 2 && *(p-3) == UC_SENTINEL)
	{
		switch(*(p-2))
		{
			case CODE_INDEX:
      case CODE_SETOPT:
      case CODE_SETSYSTEMSTORE:
				return p-3;
		}
	}
  else if(p > pStart + 3 && *(p-4) == UC_SENTINEL)
  {
    switch(*(p-3))
    {
      case CODE_IFOPT:
      case CODE_IFSYSTEMSTORE:  // I3432
        return p-4;
    }
  }
	return p;
}

int xstrlen_ignoreifopt(PWSTR p)
{
  int i;
  for(i = 0; *p; i++, p=incxstr(p))
  {
    if(*p == UC_SENTINEL && (*(p+1) == CODE_IFOPT || *(p+1) == CODE_IFSYSTEMSTORE)) i--;  // I3432
  }
  return i;
}

int xstrlen(PWSTR p)
{
	int i;
	for(i = 0; *p; i++, p=incxstr(p));
	return i;
}

int xstrpos(PWSTR p1, PWSTR p)
{
  int i;
	for(i = 0; p < p1; p = incxstr(p), i++);
	return i;
}

/*PWSTR xstrchr(PWSTR buf, int x)
{
	int clow, chigh;
	if(x < 0x10000) { chigh = x; clow = -1; }
	else { chigh = Uni_UTF32ToSurrogate1(x); clow = Uni_UTF32ToSurrogate2(x); }

	for(; *buf; buf = incxstr(buf))
		if(*buf == chigh && (*(buf+1) == clow || clow == -1)) return buf;
	return NULL;
}*/

PWSTR xstrchr(PWSTR buf, PWSTR chr)
{
  for(PWSTR q = incxstr(buf); *buf; buf = q, q = incxstr(buf))
    if(!wcsncmp(buf, chr, (int)(q-buf)))
      return buf;
  return NULL;
}

int xchrcmp(PWSTR ch1, PWSTR ch2)
{
  PWSTR nch1 = incxstr(ch1);
  if(nch1 == ch1) return *ch2 - *ch1; /* comparing *ch2 to nul */
  return wcsncmp(ch1, ch2, (int)(nch1-ch1));
}
<commit_msg>fix(windows): pointer casts for x64<commit_after>/*
  Name:             xstring
  Copyright:        Copyright (C) 2003-2017 SIL International.
  Documentation:
  Description:
  Create Date:      27 Aug 2012

  Modified Date:    27 Aug 2012
  Authors:          mcdurdin
  Related Files:
  Dependencies:

  Bugs:
  Todo:
  Notes:
  History:          27 Aug 2012 - mcdurdin - I3439 - V9.0 - Refactor xstring support in C++ code
*/
#include "pch.h"

/*
*	int xstrlen( LPBYTE p );
*
*	Parameters:	p	Pointer to string to get length of
*
*	Returns:    length of string
*
*   Called by:  various functions
*
*	xstrlen calculates the length of a string, ignoring some special chars.
*/

PWSTR incxstr(PWSTR p)
{
	if(*p == 0) return p;
	if(*p != UC_SENTINEL)
	{
		if(*p >= 0xD800 && *p <= 0xDBFF && *(p+1) >= 0xDC00 && *(p+1) <= 0xDFFF) return p+2;
		return p+1;
	}

	p+=2;
	switch(*(p-1))
	{
		case CODE_ANY:			return p+1;
		case CODE_NOTANY:   return p+1;
		case CODE_INDEX:		return p+2;
		case CODE_USE:			return p+1;
		case CODE_DEADKEY:		return p+1;
		case CODE_EXTENDED:		p += 2; while(*p != UC_SENTINEL_EXTENDEDEND) p++; return p+1;
		case CODE_CLEARCONTEXT: return p+1;
		case CODE_CALL:			return p+1;
		case CODE_CONTEXTEX:	return p+1;
    case CODE_IFOPT:    return p+3;
    case CODE_IFSYSTEMSTORE: return p+3;
    case CODE_SETOPT:   return p+2;
    case CODE_SETSYSTEMSTORE: return p+2;
    case CODE_RESETOPT: return p+1;
    case CODE_SAVEOPT:  return p+1;
		default:				return p;
	}
}

PWSTR decxstr(PWSTR p, PWSTR pStart)
{
  if (p <= pStart) {
    assert("Attempted to move prior to start of string");
    return NULL;
  }

  p--;
	if(*p == UC_SENTINEL_EXTENDEDEND)
	{
		int n = 0;
		while(*p != UC_SENTINEL && n < 10) { p--; n++; }

    if (p < pStart) {
      // May be a malformed virtual key
      return pStart;
    }
    return p;
	}

  if (p == pStart) return p; // Don't allow test before pStart

  if(*p >= 0xDC00 && *p <= 0xDFFF && *(p-1) >= 0xD800 && *(p-1) <= 0xDBFF)
	{
		return p-1;
	}
	else if(*(p-1) == UC_SENTINEL) return p-1;
	else if(p > pStart + 1 && *(p-2) == UC_SENTINEL)
	{
		switch(*(p-1))
		{
			case CODE_ANY:
			case CODE_NOTANY:
			case CODE_USE:
			case CODE_DEADKEY:
			case CODE_CLEARCONTEXT:
			case CODE_CALL:
			case CODE_CONTEXTEX:
      case CODE_RESETOPT:
      case CODE_SAVEOPT:
        return p-2;
		}
	}
	else if(p > pStart + 2 && *(p-3) == UC_SENTINEL)
	{
		switch(*(p-2))
		{
			case CODE_INDEX:
      case CODE_SETOPT:
      case CODE_SETSYSTEMSTORE:
				return p-3;
		}
	}
  else if(p > pStart + 3 && *(p-4) == UC_SENTINEL)
  {
    switch(*(p-3))
    {
      case CODE_IFOPT:
      case CODE_IFSYSTEMSTORE:  // I3432
        return p-4;
    }
  }
	return p;
}

int xstrlen_ignoreifopt(PWSTR p)
{
  int i;
  for(i = 0; *p; i++, p=incxstr(p))
  {
    if(*p == UC_SENTINEL && (*(p+1) == CODE_IFOPT || *(p+1) == CODE_IFSYSTEMSTORE)) i--;  // I3432
  }
  return i;
}

int xstrlen(PWSTR p)
{
	int i;
	for(i = 0; *p; i++, p=incxstr(p));
	return i;
}

int xstrpos(PWSTR p1, PWSTR p)
{
  int i;
	for(i = 0; p < p1; p = incxstr(p), i++);
	return i;
}

/*PWSTR xstrchr(PWSTR buf, int x)
{
	int clow, chigh;
	if(x < 0x10000) { chigh = x; clow = -1; }
	else { chigh = Uni_UTF32ToSurrogate1(x); clow = Uni_UTF32ToSurrogate2(x); }

	for(; *buf; buf = incxstr(buf))
		if(*buf == chigh && (*(buf+1) == clow || clow == -1)) return buf;
	return NULL;
}*/

PWSTR xstrchr(PWSTR buf, PWSTR chr)
{
  for(PWSTR q = incxstr(buf); *buf; buf = q, q = incxstr(buf))
    if(!wcsncmp(buf, chr, (intptr_t)(q-buf)))
      return buf;
  return NULL;
}

int xchrcmp(PWSTR ch1, PWSTR ch2)
{
  PWSTR nch1 = incxstr(ch1);
  if(nch1 == ch1) return *ch2 - *ch1; /* comparing *ch2 to nul */
  return wcsncmp(ch1, ch2, (intptr_t)(nch1-ch1));
}
<|endoftext|>


<commit_before>#include <iostream>

#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Window/Event.hpp>

#include "gui/cursor.hpp"
#include "gui/scene.hpp"

#include "engine/board.hpp"

#include "eventsystem/eventsystem.hpp"
#include "eventsystem/inputevents.hpp"

#include "foundation/spritecomponent.hpp"

#include "game/events.hpp"

namespace qrw
{

Cursor::Cursor()
	: SquareMarker(),
	  EventHandler()
{}

Cursor::~Cursor()
{
}

bool Cursor::handleEvent(const IEvent& event)
{
	if(event.getName() == MouseMovedEvent::name)
    {
		const MouseMovedEvent& moveEvent = static_cast<const MouseMovedEvent&>(event);

        sf::Vector2f newPosition;
		sf::Vector2f size = m_spriteComponent->getSize();

		newPosition.x = moveEvent.worldCoordinates.x - (moveEvent.worldCoordinates.x % (int)size.x);
		newPosition.y = moveEvent.worldCoordinates.y - (moveEvent.worldCoordinates.y % (int)size.y);

        Coordinates newBoardPosition((int)newPosition.x / size.x, (int)newPosition.y / size.y);

		if(newBoardPosition != m_boardPosition)
        {
			Board* board = g_scene.getSingleGameObject<Board>();
			if(board->isOnBoard(newBoardPosition))
            {
				setBoardPosition(newBoardPosition);
				 setVisible(true);
            }
            else
            {
				setVisible(false);
            }

			CursorMovedEvent* event = new CursorMovedEvent(m_boardPosition);
			g_eventSystem.pushEvent(event);
        }
    }
	else if(isVisible())
	{
		if(event.getName() == LeftMouseButtonPressedEvent::name)
			g_eventSystem.pushEvent(new CursorLeftClickedEvent(m_boardPosition));
		else if(event.getName() == RightMouseButtonPressedEvent::name)
			g_eventSystem.pushEvent(new CursorRightClickedEvent(m_boardPosition));
	}

	return false;
}

} // namespace qrwar
<commit_msg>Fix cursor visibility toggle on board borders<commit_after>#include <iostream>
#include <math.h>

#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Window/Event.hpp>

#include "gui/cursor.hpp"
#include "gui/scene.hpp"

#include "engine/board.hpp"

#include "eventsystem/eventsystem.hpp"
#include "eventsystem/inputevents.hpp"

#include "foundation/spritecomponent.hpp"

#include "game/events.hpp"

namespace qrw
{

Cursor::Cursor()
	: SquareMarker(),
	  EventHandler()
{}

Cursor::~Cursor()
{
}

bool Cursor::handleEvent(const IEvent& event)
{
	static int counter = 0;

	if(event.getName() == MouseMovedEvent::name)
    {
		const MouseMovedEvent& moveEvent = static_cast<const MouseMovedEvent&>(event);

		sf::Vector2f size = m_spriteComponent->getSize();

        Coordinates newBoardPosition(
			floor(moveEvent.worldCoordinates.x / size.x),
			floor(moveEvent.worldCoordinates.y / size.y));

		if(newBoardPosition != m_boardPosition)
        {
			Board* board = g_scene.getSingleGameObject<Board>();
			if(board->isOnBoard(newBoardPosition))
            {
				setBoardPosition(newBoardPosition);
				setVisible(true);
            }
            else
            {
				m_boardPosition = {-1, -1};
				setVisible(false);
            }

			CursorMovedEvent* event = new CursorMovedEvent(m_boardPosition);
			g_eventSystem.pushEvent(event);
        }
    }
	else if(isVisible())
	{
		if(event.getName() == LeftMouseButtonPressedEvent::name)
			g_eventSystem.pushEvent(new CursorLeftClickedEvent(m_boardPosition));
		else if(event.getName() == RightMouseButtonPressedEvent::name)
			g_eventSystem.pushEvent(new CursorRightClickedEvent(m_boardPosition));
	}

	return false;
}

} // namespace qrwar
<|endoftext|>