<commit_before>/* Copyright (c) 2010-2013, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <QDir>
#include <QTextCodec>
#include <QDateTime>
#include <TWebApplication>
#include <TSystemGlobal>
#include <stdlib.h>

#define DEFAULT_INTERNET_MEDIA_TYPE   "text/plain"
#define DEFAULT_DATABASE_ENVIRONMENT  "product"

static QTextCodec *searchCodec(const char *name)
{
    QTextCodec *c = QTextCodec::codecForName(name);
    return (c) ? c : QTextCodec::codecForLocale();
}

/*!
  \class TWebApplication
  \brief The TWebApplication class provides an event loop for
  TreeFrog applications.
*/

/*!
  Constructor.
*/
TWebApplication::TWebApplication(int &argc, char **argv)
#ifdef TF_USE_GUI_MODULE
    : QApplication(argc, argv),
#else
    : QCoreApplication(argc, argv),
#endif
      dbEnvironment(DEFAULT_DATABASE_ENVIRONMENT),
      appSetting(0),
      sqlSettings(0),
      mongoSetting(0),
      loggerSetting(0),
      validationSetting(0),
      mediaTypes(0),
      codecInternal(0),
      codecHttp(0),
      mpm(Invalid)
{
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
    installNativeEventFilter(new TNativeEventFilter);
#endif

    // parse command-line args
    webRootAbsolutePath = ".";
    QStringList args = arguments();
    args.removeFirst();
    for (QStringListIterator i(args); i.hasNext(); ) {
        const QString &arg = i.next();
        if (arg.startsWith('-')) {
            if (arg == "-e" && i.hasNext()) {
                dbEnvironment = i.next();
            }
        } else {
            if (QDir(arg).exists()) {
                webRootAbsolutePath = arg;
                if (!webRootAbsolutePath.endsWith(QDir::separator()))
                    webRootAbsolutePath += QDir::separator();
            }
        }
    }

    QDir webRoot(webRootAbsolutePath);
    if (webRoot.exists()) {
        webRootAbsolutePath = webRoot.absolutePath() + QDir::separator();
    }

    // Sets application name
    QString appName = QDir(webRootAbsolutePath).dirName();
    if (!appName.isEmpty()) {
        setApplicationName(appName);
    }

    // Creates settings objects
    appSetting = new QSettings(appSettingsFilePath(), QSettings::IniFormat, this);
    loggerSetting = new QSettings(configPath() + "logger.ini", QSettings::IniFormat, this);
    validationSetting = new QSettings(configPath() + "validation.ini", QSettings::IniFormat, this);
    mediaTypes = new QSettings(configPath() + "initializers" + QDir::separator() + "internet_media_types.ini", QSettings::IniFormat, this);

    // Gets codecs
    codecInternal = searchCodec(appSetting->value("InternalEncoding").toByteArray().trimmed().data());
    codecHttp = searchCodec(appSetting->value("HttpOutputEncoding").toByteArray().trimmed().data());

    // Sets codecs for INI files
    loggerSetting->setIniCodec(codecInternal);
    validationSetting->setIniCodec(codecInternal);
    mediaTypes->setIniCodec(codecInternal);

    // SQL DB settings
    QString dbsets = appSetting->value("SqlDatabaseSettingsFiles").toString().trimmed();
    if (dbsets.isEmpty()) {
        dbsets = appSetting->value("DatabaseSettingsFiles").toString().trimmed();
    }
    QStringList files = dbsets.split(QLatin1Char(' '), QString::SkipEmptyParts);
    for (QListIterator<QString> it(files); it.hasNext(); ) {
        const QString &f = it.next();
        QSettings *set = new QSettings(configPath() + f, QSettings::IniFormat, this);
        set->setIniCodec(codecInternal);
        sqlSettings.append(set);
    }

    // MongoDB settings
    QString mongoini = appSetting->value("MongoDbSettingsFile").toString().trimmed();
    if (!mongoini.isEmpty()) {
        mongoSetting = new QSettings(configPath() + mongoini, QSettings::IniFormat, this);
    }

    // sets a seed for random numbers
    Tf::srandXor128((QDateTime::currentDateTime().toTime_t() << 14) | (QCoreApplication::applicationPid() & 0x3fff));
}

TWebApplication::~TWebApplication()
{ }

/*!
  Enters the main event loop and waits until exit() is called. Returns the
  value that was set to exit() (which is 0 if exit() is called via quit()).
*/
int TWebApplication::exec()
{
    resetSignalNumber();
#ifdef TF_USE_GUI_MODULE
    return QApplication::exec();
#else
    return QCoreApplication::exec();
#endif
}

/*!
  Returns true if the web root directory exists; otherwise returns false.
*/
bool TWebApplication::webRootExists() const
{
    return !webRootAbsolutePath.isEmpty() && QDir(webRootAbsolutePath).exists();
}

/*!
  Returns the absolute path of the public directory.
*/
QString TWebApplication::publicPath() const
{
    return webRootPath() + "public" + QDir::separator();
}

/*!
  Returns the absolute path of the config directory.
*/
QString TWebApplication::configPath() const
{
    return webRootPath() + "config" + QDir::separator();
}

/*!
  Returns the absolute path of the library directory.
*/
QString TWebApplication::libPath() const
{
    return webRootPath()+ "lib" + QDir::separator();
}

/*!
  Returns the absolute path of the log directory.
*/
QString TWebApplication::logPath() const
{
    return webRootPath() + "log" + QDir::separator();
}

/*!
  Returns the absolute path of the plugin directory.
*/
QString TWebApplication::pluginPath() const
{
    return webRootPath() + "plugin" + QDir::separator();
}

/*!
  Returns the absolute path of the tmp directory.
*/
QString TWebApplication::tmpPath() const
{
    return webRootPath() + "tmp" + QDir::separator();
}

/*!
  Returns true if the file of the application settings exists;
  otherwise returns false.
*/
bool TWebApplication::appSettingsFileExists() const
{
    return !appSetting->allKeys().isEmpty();
}

/*!
  Returns the absolute file path of the application settings.
*/
QString TWebApplication::appSettingsFilePath() const
{
    return configPath() + "application.ini";
}

/*!
  Returns a reference to the QSettings object for settings of the
  SQL database \a databaseId.
*/
QSettings &TWebApplication::sqlDatabaseSettings(int databaseId) const
{
    return *sqlSettings[databaseId];
}

/*!
  Returns the number of SQL database settings files set by the setting
  \a DatabaseSettingsFiles in the application.ini.
*/
int TWebApplication::sqlDatabaseSettingsCount() const
{
    return sqlSettings.count();
}

/*!
  Returns true if SQL database is available; otherwise returns false.
*/
bool TWebApplication::isSqlDatabaseAvailable() const
{
    return sqlSettings.count() > 0;
}

/*!
  Returns a reference to the QSettings object for settings of the
  MongoDB system.
*/
QSettings &TWebApplication::mongoDbSettings() const
{
    return *mongoSetting;
}

/*!
  Returns true if MongoDB is available; otherwise returns false.
*/
bool TWebApplication::isMongoDbAvailable() const
{
#ifdef TF_BUILD_MONGODB
    return (bool)mongoSetting;
#else
    return false;
#endif
}

/*!
  Returns the internet media type associated with the file extension
  \a ext.
*/
QByteArray TWebApplication::internetMediaType(const QString &ext, bool appendCharset)
{
    if (ext.isEmpty())
        return QByteArray();

    QString type = mediaTypes->value(ext, DEFAULT_INTERNET_MEDIA_TYPE).toString();
    if (appendCharset && type.startsWith("text", Qt::CaseInsensitive)) {
        type += "; charset=" + Tf::app()->codecForHttpOutput()->name();
    }
    return type.toLatin1();
}

/*!
  Returns the error message for validation of the given \a rule. These messages
  are defined in the validation.ini.
*/
QString TWebApplication::validationErrorMessage(int rule) const
{
    validationSetting->beginGroup("ErrorMessage");
    QString msg = validationSetting->value(QString::number(rule)).toString();
    validationSetting->endGroup();
    return msg;
}

/*!
  Returns the module name for multi-processing that is set by the setting
  \a MultiProcessingModule in the application.ini.
*/
TWebApplication::MultiProcessingModule TWebApplication::multiProcessingModule() const
{
    if (mpm == Invalid) {
        QString str = appSettings().value("MultiProcessingModule").toString().toLower();
        if (str == "thread") {
            mpm = Thread;
        } else if (str == "prefork") {
            mpm = Prefork;
        }
    }
    return mpm;
}

/*!
  Returns the maximum number of runnable servers, which is set in the
  application.ini.
*/
int TWebApplication::maxNumberOfServers() const
{
    QString mpm = appSettings().value("MultiProcessingModule").toString().toLower();
    int num = appSettings().value(QLatin1String("MPM.") + mpm + ".MaxServers").toInt();
    Q_ASSERT(num > 0);
    return num;
}

/*!
  Returns the absolute file path of the routes config.
*/
QString TWebApplication::routesConfigFilePath() const
{
    return configPath() + "routes.cfg";
}

/*!
  Returns the absolute file path of the system log, which is set by the
  setting \a SystemLog.FilePath in the application.ini.
*/
QString TWebApplication::systemLogFilePath() const
{
    QFileInfo fi(appSettings().value("SystemLog.FilePath", "log/treefrog.log").toString());
    return (fi.isAbsolute()) ? fi.absoluteFilePath() : webRootPath() + fi.filePath();
}

/*!
  Returns the absolute file path of the access log, which is set by the
  setting \a AccessLog.FilePath in the application.ini.
*/
QString TWebApplication::accessLogFilePath() const
{
    QFileInfo fi(appSettings().value("AccessLog.FilePath", "log/access.log").toString());
    return (fi.isAbsolute()) ? fi.absoluteFilePath() : webRootPath() + fi.filePath();
}

/*!
  Returns the absolute file path of the SQL query log, which is set by the
  setting \a SqlQueryLogFile in the application.ini.
*/
QString TWebApplication::sqlQueryLogFilePath() const
{
    QString path = appSettings().value("SqlQueryLogFile").toString();
    if (!path.isEmpty()) {
        QFileInfo fi(path);
        path = (fi.isAbsolute()) ? fi.absoluteFilePath() : webRootPath() + fi.filePath();
    }
    return path;
}

void TWebApplication::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == timer.timerId()) {
        if (signalNumber() >= 0) {
            tSystemDebug("TWebApplication trapped signal  number:%d", signalNumber());
            exit(signalNumber());
        }
    } else {
#ifdef TF_USE_GUI_MODULE
        QApplication::timerEvent(event);
#else
        QCoreApplication::timerEvent(event);
#endif
    }
}

/*!
  \fn QString TWebApplication::webRootPath() const
  Returns the absolute path of the web root directory.
*/

/*!
  \fn QSettings &TWebApplication::appSettings() const
  Returns a reference to the QSettings object for settings of the
  web application, which file is the application.ini.
*/

/*!
  \fn QSettings &TWebApplication::loggerSettings () const
  Returns a reference to the QSettings object for settings of the
  logger, which file is logger.ini.
*/

/*!
  \fn QSettings &TWebApplication::validationSettings () const
  Returns a reference to the QSettings object for settings of the
  validation, which file is validation.ini.
*/

/*!
  \fn QTextCodec *TWebApplication::codecForInternal() const
  Returns a pointer to the codec used internally, which is set by the
  setting \a InternalEncoding in the application.ini. This codec is used
  by QObject::tr() and toLocal8Bit() functions.
*/

/*!
  \fn QTextCodec *TWebApplication::codecForHttpOutput() const
  Returns a pointer to the codec of the HTTP output stream used by an
  action view, which is set by the setting \a HttpOutputEncoding in
  the application.ini.
*/

/*!
  \fn QString TWebApplication::databaseEnvironment() const
  Returns the database environment, which string is used to load
  the settings in database.ini.
  \sa setDatabaseEnvironment(const QString &environment)
*/

/*!
  \fn void TWebApplication::watchConsoleSignal();
  Starts watching console signals i.e.\ registers a routine to handle the
  console signals.
*/

/*!
  \fn void TWebApplication::ignoreConsoleSignal();
  Ignores console signals, i.e.\ delivery of console signals will have no effect
  on the process.
*/

/*!
  \fn void TWebApplication::watchUnixSignal(int sig, bool watch);
  Starts watching the UNIX signal, i.e.\ registers a routine to handle the
  signal \a sig.
  \sa ignoreUnixSignal()
*/

/*!
  \fn void TWebApplication::ignoreUnixSignal(int sig, bool ignore)
  Ignores UNIX signals, i.e.\ delivery of the signal will have no effect on
  the process.
  \sa watchUnixSignal()
*/

/*!
  \fn void TWebApplication::timerEvent(QTimerEvent *)
  Reimplemented from QObject::timerEvent().
*/

/*!
  \fn int TWebApplication::signalNumber()
  Returns the integral number of the received signal.
*/
<commit_msg>add cleanup code<commit_after>/* Copyright (c) 2010-2013, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <QDir>
#include <QTextCodec>
#include <QDateTime>
#include <TWebApplication>
#include <TSystemGlobal>
#include <stdlib.h>

#define DEFAULT_INTERNET_MEDIA_TYPE   "text/plain"
#define DEFAULT_DATABASE_ENVIRONMENT  "product"

static QTextCodec *searchCodec(const char *name)
{
    QTextCodec *c = QTextCodec::codecForName(name);
    return (c) ? c : QTextCodec::codecForLocale();
}

/*!
  \class TWebApplication
  \brief The TWebApplication class provides an event loop for
  TreeFrog applications.
*/

/*!
  Constructor.
*/
TWebApplication::TWebApplication(int &argc, char **argv)
#ifdef TF_USE_GUI_MODULE
    : QApplication(argc, argv),
#else
    : QCoreApplication(argc, argv),
#endif
      dbEnvironment(DEFAULT_DATABASE_ENVIRONMENT),
      appSetting(0),
      sqlSettings(0),
      mongoSetting(0),
      loggerSetting(0),
      validationSetting(0),
      mediaTypes(0),
      codecInternal(0),
      codecHttp(0),
      mpm(Invalid)
{
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
    installNativeEventFilter(new TNativeEventFilter);
#endif

    // parse command-line args
    webRootAbsolutePath = ".";
    QStringList args = arguments();
    args.removeFirst();
    for (QStringListIterator i(args); i.hasNext(); ) {
        const QString &arg = i.next();
        if (arg.startsWith('-')) {
            if (arg == "-e" && i.hasNext()) {
                dbEnvironment = i.next();
            }
        } else {
            if (QDir(arg).exists()) {
                webRootAbsolutePath = arg;
                if (!webRootAbsolutePath.endsWith(QDir::separator()))
                    webRootAbsolutePath += QDir::separator();
            }
        }
    }

    QDir webRoot(webRootAbsolutePath);
    if (webRoot.exists()) {
        webRootAbsolutePath = webRoot.absolutePath() + QDir::separator();
    }

    // Sets application name
    QString appName = QDir(webRootAbsolutePath).dirName();
    if (!appName.isEmpty()) {
        setApplicationName(appName);
    }

    // Creates settings objects
    appSetting = new QSettings(appSettingsFilePath(), QSettings::IniFormat, this);
    loggerSetting = new QSettings(configPath() + "logger.ini", QSettings::IniFormat, this);
    validationSetting = new QSettings(configPath() + "validation.ini", QSettings::IniFormat, this);
    mediaTypes = new QSettings(configPath() + "initializers" + QDir::separator() + "internet_media_types.ini", QSettings::IniFormat, this);

    // Gets codecs
    codecInternal = searchCodec(appSetting->value("InternalEncoding").toByteArray().trimmed().data());
    codecHttp = searchCodec(appSetting->value("HttpOutputEncoding").toByteArray().trimmed().data());

    // Sets codecs for INI files
    loggerSetting->setIniCodec(codecInternal);
    validationSetting->setIniCodec(codecInternal);
    mediaTypes->setIniCodec(codecInternal);

    // SQL DB settings
    QString dbsets = appSetting->value("SqlDatabaseSettingsFiles").toString().trimmed();
    if (dbsets.isEmpty()) {
        dbsets = appSetting->value("DatabaseSettingsFiles").toString().trimmed();
    }
    QStringList files = dbsets.split(QLatin1Char(' '), QString::SkipEmptyParts);
    for (QListIterator<QString> it(files); it.hasNext(); ) {
        const QString &f = it.next();
        QSettings *set = new QSettings(configPath() + f, QSettings::IniFormat, this);
        set->setIniCodec(codecInternal);
        sqlSettings.append(set);
    }

    // MongoDB settings
    QString mongoini = appSetting->value("MongoDbSettingsFile").toString().trimmed();
    if (!mongoini.isEmpty()) {
        mongoSetting = new QSettings(configPath() + mongoini, QSettings::IniFormat, this);
    }

    // sets a seed for random numbers
    Tf::srandXor128((QDateTime::currentDateTime().toTime_t() << 14) | (QCoreApplication::applicationPid() & 0x3fff));
}

TWebApplication::~TWebApplication()
{ }

/*!
  Enters the main event loop and waits until exit() is called. Returns the
  value that was set to exit() (which is 0 if exit() is called via quit()).
*/
int TWebApplication::exec()
{
    resetSignalNumber();

#ifdef TF_USE_GUI_MODULE
    int ret = QApplication::exec();
#else
    int ret = QCoreApplication::exec();
#endif

    QEventLoop eventLoop;
    while (eventLoop.processEvents()) { }
    return ret;
}

/*!
  Returns true if the web root directory exists; otherwise returns false.
*/
bool TWebApplication::webRootExists() const
{
    return !webRootAbsolutePath.isEmpty() && QDir(webRootAbsolutePath).exists();
}

/*!
  Returns the absolute path of the public directory.
*/
QString TWebApplication::publicPath() const
{
    return webRootPath() + "public" + QDir::separator();
}

/*!
  Returns the absolute path of the config directory.
*/
QString TWebApplication::configPath() const
{
    return webRootPath() + "config" + QDir::separator();
}

/*!
  Returns the absolute path of the library directory.
*/
QString TWebApplication::libPath() const
{
    return webRootPath()+ "lib" + QDir::separator();
}

/*!
  Returns the absolute path of the log directory.
*/
QString TWebApplication::logPath() const
{
    return webRootPath() + "log" + QDir::separator();
}

/*!
  Returns the absolute path of the plugin directory.
*/
QString TWebApplication::pluginPath() const
{
    return webRootPath() + "plugin" + QDir::separator();
}

/*!
  Returns the absolute path of the tmp directory.
*/
QString TWebApplication::tmpPath() const
{
    return webRootPath() + "tmp" + QDir::separator();
}

/*!
  Returns true if the file of the application settings exists;
  otherwise returns false.
*/
bool TWebApplication::appSettingsFileExists() const
{
    return !appSetting->allKeys().isEmpty();
}

/*!
  Returns the absolute file path of the application settings.
*/
QString TWebApplication::appSettingsFilePath() const
{
    return configPath() + "application.ini";
}

/*!
  Returns a reference to the QSettings object for settings of the
  SQL database \a databaseId.
*/
QSettings &TWebApplication::sqlDatabaseSettings(int databaseId) const
{
    return *sqlSettings[databaseId];
}

/*!
  Returns the number of SQL database settings files set by the setting
  \a DatabaseSettingsFiles in the application.ini.
*/
int TWebApplication::sqlDatabaseSettingsCount() const
{
    return sqlSettings.count();
}

/*!
  Returns true if SQL database is available; otherwise returns false.
*/
bool TWebApplication::isSqlDatabaseAvailable() const
{
    return sqlSettings.count() > 0;
}

/*!
  Returns a reference to the QSettings object for settings of the
  MongoDB system.
*/
QSettings &TWebApplication::mongoDbSettings() const
{
    return *mongoSetting;
}

/*!
  Returns true if MongoDB is available; otherwise returns false.
*/
bool TWebApplication::isMongoDbAvailable() const
{
#ifdef TF_BUILD_MONGODB
    return (bool)mongoSetting;
#else
    return false;
#endif
}

/*!
  Returns the internet media type associated with the file extension
  \a ext.
*/
QByteArray TWebApplication::internetMediaType(const QString &ext, bool appendCharset)
{
    if (ext.isEmpty())
        return QByteArray();

    QString type = mediaTypes->value(ext, DEFAULT_INTERNET_MEDIA_TYPE).toString();
    if (appendCharset && type.startsWith("text", Qt::CaseInsensitive)) {
        type += "; charset=" + Tf::app()->codecForHttpOutput()->name();
    }
    return type.toLatin1();
}

/*!
  Returns the error message for validation of the given \a rule. These messages
  are defined in the validation.ini.
*/
QString TWebApplication::validationErrorMessage(int rule) const
{
    validationSetting->beginGroup("ErrorMessage");
    QString msg = validationSetting->value(QString::number(rule)).toString();
    validationSetting->endGroup();
    return msg;
}

/*!
  Returns the module name for multi-processing that is set by the setting
  \a MultiProcessingModule in the application.ini.
*/
TWebApplication::MultiProcessingModule TWebApplication::multiProcessingModule() const
{
    if (mpm == Invalid) {
        QString str = appSettings().value("MultiProcessingModule").toString().toLower();
        if (str == "thread") {
            mpm = Thread;
        } else if (str == "prefork") {
            mpm = Prefork;
        }
    }
    return mpm;
}

/*!
  Returns the maximum number of runnable servers, which is set in the
  application.ini.
*/
int TWebApplication::maxNumberOfServers() const
{
    QString mpm = appSettings().value("MultiProcessingModule").toString().toLower();
    int num = appSettings().value(QLatin1String("MPM.") + mpm + ".MaxServers").toInt();
    Q_ASSERT(num > 0);
    return num;
}

/*!
  Returns the absolute file path of the routes config.
*/
QString TWebApplication::routesConfigFilePath() const
{
    return configPath() + "routes.cfg";
}

/*!
  Returns the absolute file path of the system log, which is set by the
  setting \a SystemLog.FilePath in the application.ini.
*/
QString TWebApplication::systemLogFilePath() const
{
    QFileInfo fi(appSettings().value("SystemLog.FilePath", "log/treefrog.log").toString());
    return (fi.isAbsolute()) ? fi.absoluteFilePath() : webRootPath() + fi.filePath();
}

/*!
  Returns the absolute file path of the access log, which is set by the
  setting \a AccessLog.FilePath in the application.ini.
*/
QString TWebApplication::accessLogFilePath() const
{
    QFileInfo fi(appSettings().value("AccessLog.FilePath", "log/access.log").toString());
    return (fi.isAbsolute()) ? fi.absoluteFilePath() : webRootPath() + fi.filePath();
}

/*!
  Returns the absolute file path of the SQL query log, which is set by the
  setting \a SqlQueryLogFile in the application.ini.
*/
QString TWebApplication::sqlQueryLogFilePath() const
{
    QString path = appSettings().value("SqlQueryLogFile").toString();
    if (!path.isEmpty()) {
        QFileInfo fi(path);
        path = (fi.isAbsolute()) ? fi.absoluteFilePath() : webRootPath() + fi.filePath();
    }
    return path;
}

void TWebApplication::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == timer.timerId()) {
        if (signalNumber() >= 0) {
            tSystemDebug("TWebApplication trapped signal  number:%d", signalNumber());
            exit(signalNumber());
        }
    } else {
#ifdef TF_USE_GUI_MODULE
        QApplication::timerEvent(event);
#else
        QCoreApplication::timerEvent(event);
#endif
    }
}

/*!
  \fn QString TWebApplication::webRootPath() const
  Returns the absolute path of the web root directory.
*/

/*!
  \fn QSettings &TWebApplication::appSettings() const
  Returns a reference to the QSettings object for settings of the
  web application, which file is the application.ini.
*/

/*!
  \fn QSettings &TWebApplication::loggerSettings () const
  Returns a reference to the QSettings object for settings of the
  logger, which file is logger.ini.
*/

/*!
  \fn QSettings &TWebApplication::validationSettings () const
  Returns a reference to the QSettings object for settings of the
  validation, which file is validation.ini.
*/

/*!
  \fn QTextCodec *TWebApplication::codecForInternal() const
  Returns a pointer to the codec used internally, which is set by the
  setting \a InternalEncoding in the application.ini. This codec is used
  by QObject::tr() and toLocal8Bit() functions.
*/

/*!
  \fn QTextCodec *TWebApplication::codecForHttpOutput() const
  Returns a pointer to the codec of the HTTP output stream used by an
  action view, which is set by the setting \a HttpOutputEncoding in
  the application.ini.
*/

/*!
  \fn QString TWebApplication::databaseEnvironment() const
  Returns the database environment, which string is used to load
  the settings in database.ini.
  \sa setDatabaseEnvironment(const QString &environment)
*/

/*!
  \fn void TWebApplication::watchConsoleSignal();
  Starts watching console signals i.e.\ registers a routine to handle the
  console signals.
*/

/*!
  \fn void TWebApplication::ignoreConsoleSignal();
  Ignores console signals, i.e.\ delivery of console signals will have no effect
  on the process.
*/

/*!
  \fn void TWebApplication::watchUnixSignal(int sig, bool watch);
  Starts watching the UNIX signal, i.e.\ registers a routine to handle the
  signal \a sig.
  \sa ignoreUnixSignal()
*/

/*!
  \fn void TWebApplication::ignoreUnixSignal(int sig, bool ignore)
  Ignores UNIX signals, i.e.\ delivery of the signal will have no effect on
  the process.
  \sa watchUnixSignal()
*/

/*!
  \fn void TWebApplication::timerEvent(QTimerEvent *)
  Reimplemented from QObject::timerEvent().
*/

/*!
  \fn int TWebApplication::signalNumber()
  Returns the integral number of the received signal.
*/
<|endoftext|>


<commit_before>// <experimental/Any> -*- C++ -*-

// Copyright (C) 2014-2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// Any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT Any WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file experimental/any
 *  This is a TS C++ Library header.
 */

#ifndef RADIUMENGINE_ANY_HPP
#define RADIUMENGINE_ANY_HPP

#include <typeinfo>
#include <new>
#include <utility>
#include <type_traits>
#include <iostream>

#include <Core/CoreMacros.hpp>

#ifndef COMPILER_MSVC
using std::type_info; // Use type_info instead of std::type_info in order to build properly with MSVC
#endif

namespace Ra {
    namespace Core {
        template<typename...> struct Or;
        template<> struct Or<> : public std::false_type { };
        template<typename T> struct Or<T> : public T { };
        template<typename T, typename U> struct Or<T, U> : public std::conditional<T::value, U, U>::type { };

        template<typename T, typename U, typename V, typename... Tn>
        struct Or<T, U, V, Tn...> : public std::conditional<T::value, T, Or>::type { };

        /**
         *  @brief A type-safe container of any type.
         *
         *  An @c any object's state is either empty or it stores a contained object
         *  of CopyConstructible type.
         */
        class Any
        {
            // Holds either pointer to a heap object or the contained object itself.
            union Storage
            {
                void* m_ptr;
                std::aligned_storage<sizeof( void* ), sizeof( void* )>::type m_buffer;
            };

            template < typename T, typename Safe = std::is_trivially_copyable<T>,
                       bool TFits = ( sizeof( T ) <= sizeof( Storage ) ) >
                       using Internal = std::integral_constant < bool, Safe::value && TFits >;

            template<typename T>
            struct ManagerInternal; // uses small-object optimization

            template<typename T>
            struct ManagerExternal; // creates contained object on the heap

            template<typename T>
            using Manager = std::conditional_t<Internal<T>::value,
                                               ManagerInternal<T>,
                                               ManagerExternal<T>>;

            template<typename T, typename Decayed = std::decay_t<T>>
            using Decay = std::enable_if_t < !std::is_same<Decayed, Any>::value, Decayed >;

        public:
            // construct/destruct

            /// Default constructor, creates an empty object.
            Any() noexcept
                : m_manager( nullptr ) { }

            /// Copy constructor, copies the state of @p other
            Any( const Any& other )
                : m_manager( other.m_manager )
            {
                if ( !other.empty() )
                {
                    Arg arg;
                    arg.m_any = this;
                    m_manager( OP_CLONE, &other, &arg );
                }
            }

            /**
             * @brief Move constructor, transfer the state from @p other
             *
             * @post @c other.empty() (not guaranteed for other implementations)
             */
            Any( Any&& other ) noexcept
                : m_manager( other.m_manager )
                , m_storage( other.m_storage )
            {
                other.m_manager = nullptr;
            }

            /// Construct with a copy of @p value as the contained object.
            template <typename V, typename T = Decay<V>, typename _Mgr = Manager<T>> Any( V && value )
                : m_manager( &_Mgr::manager )
                , m_storage( _Mgr::create( std::forward<V>( value ) ) )
            {
                static_assert( std::is_copy_constructible<T>::value,
                               "The contained object must be CopyConstructible" );
            }

            /// Destructor, calls @c clear()
            ~Any()
            {
                clear();
            }

            // assignments

            /// Copy the state of
            Any& operator=( const Any& rhs )
            {
                Any( rhs ).swap( *this );
                return *this;
            }

            /**
             * @brief Move assignment operator
             *
             * @post @c rhs.empty() (not guaranteed for other implementations)
             */
            Any& operator=( Any && rhs ) noexcept
            {
                Any( std::move( rhs ) ).swap( *this );
                return *this;
            }

            /// Store a copy of @p rhs as the contained object.
            template<typename V> Any& operator=( V && rhs )
            {
                Any( std::forward<V>( rhs ) ).swap( *this );
                return *this;
            }

            // modifiers

            /// If not empty, destroy the contained object.
            void clear() noexcept
            {
                if ( !empty() )
                {
                    m_manager( OP_DESTROY, this, nullptr );
                    m_manager = nullptr;
                }
            }

            /// Exchange state with another object.
            void swap( Any& rhs ) noexcept
            {
                std::swap( m_manager, rhs.m_manager );
                std::swap( m_storage, rhs.m_storage );
            }

            // observers

            /// Reports whether there is a contained object or not.
            bool empty() const noexcept
            {
                return m_manager == nullptr;
            }

            template<typename T>
            static constexpr bool isValidCast()
            {
                return Or<std::is_reference<T>, std::is_copy_constructible<T>>::value;
            }

        private:
            enum Op { OP_ACCESS, OP_GETTYPEINFO, OP_CLONE, OP_DESTROY };

            union Arg
            {
                void* m_obj;
                const type_info* m_typeinfo;
                Any* m_any;
            };

            void ( *m_manager )( Op, const Any*, Arg* );
            Storage m_storage;

            template<typename T> friend const T* anyCast( const Any* any ) noexcept;
            template<typename T> friend T* anyCast( Any* any ) noexcept;

            template<typename T>
            static void* anyCaster( const Any* any )
            {
                if ( any->m_manager != &Manager<std::decay_t<T>>::manager )
                {
                    return nullptr;
                }
                Arg arg;
                any->m_manager( OP_ACCESS, any, &arg );
                return arg.m_obj;
            }

            // Manage in-place contained object.
            template<typename T>
            struct ManagerInternal
            {
                static void manager( Op which, const Any* anyp, Arg* arg );

                template<typename _Up>
                static Storage create( _Up&& value )
                {
                    Storage storage;
                    void* addr = &storage.m_buffer;
                    ::new( addr ) T( std::forward<_Up>( value ) );
                    return storage;
                }

                template<typename _Alloc, typename _Up>
                static Storage alloc( const _Alloc&, _Up&& value )
                {
                    return create( std::forward<_Up>( value ) );
                }
            };

            // Manage external contained object.
            template<typename T>
            struct ManagerExternal
            {
                static void manager( Op which, const Any* anyp, Arg* arg );

                template<typename _Up>
                static Storage create( _Up&& value )
                {
                    Storage storage;
                    storage.m_ptr = new T( std::forward<_Up>( value ) );
                    return storage;
                }
            };
        };

        /// Exchange the states of two @c any objects.
        inline void swap( Any& x, Any& y ) noexcept { x.swap( y ); }

        /**
         * @brief Access the contained object.
         *
         * @tparam  V  A const-reference or CopyConstructible type.
         * @param   any       The object to access.
         * @return  The contained object.
         * @throw   bad_anyCast If
         *          any.type() != typeid(remove_reference_t<V>)
         *
         */
        template<typename V>
        inline V anyCast( const Any& any )
        {
            static_assert( Any::isValidCast<V>(),
                           "Template argument must be a reference or CopyConstructible type" );
            auto p = anyCast<std::add_const_t<std::remove_reference_t<V>>>( &any );
            if ( p )
            {
                return *p;
            }
            CORE_ERROR( "Could not cast given any to required type." );

            // prevent clang warning -Wreturn-type
            return V();
        }

        /**
         * @brief Access the contained object.
         *
         * @tparam  V  A reference or CopyConstructible type.
         * @param   any       The object to access.
         * @return  The contained object.
         * @throw   bad_anyCast If
         *          any.type() != typeid(remove_reference_t<V>)
         *
         *
         * @{
         */
        template<typename V>
        inline V anyCast( Any& any )
        {
            static_assert( Any::isValidCast<V>(),
                           "Template argument must be a reference or CopyConstructible type" );
            auto p = anyCast<std::remove_reference_t<V>>( &any );
            if ( p )
            {
                return *p;
            }
            CORE_ERROR( "Could not cast given any to required type." );

            // prevent clang warning -Wreturn-type
            return V();
        }

        template<typename V>
        inline V anyCast( Any&& any )
        {
            static_assert( Any::isValidCast<V>(),
                           "Template argument must be a reference or CopyConstructible type" );
            auto p = anyCast<std::remove_reference_t<V>>( &any );
            if ( p )
            {
                return *p;
            }
            CORE_ERROR( "Could not cast given any to required type." );

            // prevent clang warning -Wreturn-type
            return V();
        }
        // @}

        /**
         * @brief Access the contained object.
         *
         * @tparam  V  The type of the contained object.
         * @param   any       A pointer to the object to access.
         * @return  The address of the contained object if
         *          any != nullptr && any.type() == typeid(V)
         *          , otherwise a null pointer.
         *
         * @{
         */
        template<typename V>
        inline const V* anyCast( const Any* any ) noexcept
        {
            if ( any )
            {
                return static_cast<V*>( Any::anyCaster<V>( any ) );
            }
            return nullptr;
        }

        template<typename V>
        inline V* anyCast( Any* any ) noexcept
        {
            if ( any )
            {
                return static_cast<V*>( Any::anyCaster<V>( any ) );
            }
            return nullptr;
        }
        // @}

        template<typename T>
        void Any::ManagerInternal<T>::manager( Op which, const Any* any, Arg* arg )
        {
            // The contained object is in m_storage.m_buffer
            auto ptr = reinterpret_cast<const T*>( &any->m_storage.m_buffer );
            switch ( which )
            {
                case OP_ACCESS:
                    arg->m_obj = const_cast<T*>( ptr );
                    break;
                case OP_GETTYPEINFO:
                    break;
                case OP_CLONE:
                    ::new( &arg->m_any->m_storage.m_buffer ) T( *ptr );
                    break;
                case OP_DESTROY:
                    ptr->~T();
                    break;
            }
        }

        template<typename T>
        void Any::ManagerExternal<T>::manager( Op which, const Any* any, Arg* arg )
        {
            // The contained object is *m_storage.m_ptr
            auto ptr = static_cast<const T*>( any->m_storage.m_ptr );
            switch ( which )
            {
                case OP_ACCESS:
                    arg->m_obj = const_cast<T*>( ptr );
                    break;
                case OP_GETTYPEINFO:
                    break;
                case OP_CLONE:
                    arg->m_any->m_storage.m_ptr = new T( *ptr );
                    break;
                case OP_DESTROY:
                    delete ptr;
                    break;
            }
        }

        template<typename T>
        bool isOfType( const Any& any, const T& dummy = T() )
        {
            return anyCast<std::add_const_t<std::remove_reference_t<T>>>( &any );
        }

        template<typename T>
        bool isOfType( Any& any, const T& dummy = T() )
        {
            return anyCast<std::remove_reference_t<T>>( &any );
        }

    } // namespace Core
} // namespace Ra

#endif // RADIUMENGINE_ANY_HPP

<commit_msg>Remove unused 'any' implementation<commit_after><|endoftext|>


<commit_before>//
//  GameController.cpp
//  CatchiOS
//
//  Created by John Barbero Unenge on 9/24/12.
//  Copyright (c) 2012 John Barbero Unenge. All rights reserved.
//

#include "GameController.hpp"
#include "Logger.hpp"
#include "InputManager.hpp"

GameController::GameController(int width, int height, const char* resourcesPath)
{
    Log(LOG_INFO, "GameController", "Constructed GameController");

    InputManager::getSharedManager()->addInputListener(this);

    m_fileManager = new FileManager(resourcesPath);
    m_renderer = new GLRenderer();
    m_renderer->init(width, height);
}
GameController::~GameController()
{
    Log(LOG_INFO, "GameController", "Destroyed GameController");
    m_renderer->~GLRenderer();
}

void GameController::setRenderer(GLRenderer* r)
{
	this->m_renderer = r;
}
GLRenderer* GameController::getRenderer()
{
	return m_renderer;
}

void GameController::didRecieveInputEvent(InputType type, int locX, int locY)
{
	Log(LOG_EVENT, "GameController",  "DidRecieveInputEvent");
    m_fileManager->loadTextureFromFile("color");
}
<commit_msg>Made the gamecontroller use the new CStringer to log multiple variables.<commit_after>//
//  GameController.cpp
//  CatchiOS
//
//  Created by John Barbero Unenge on 9/24/12.
//  Copyright (c) 2012 John Barbero Unenge. All rights reserved.
//

#include "GameController.hpp"
#include "Logger.hpp"
#include "InputManager.hpp"

GameController::GameController(int width, int height, const char* resourcesPath)
{
    Log(LOG_INFO, "GameController", generateCString("GameCon: %ix%i anPB: %s", width, height, resourcesPath));

    InputManager::getSharedManager()->addInputListener(this);

    m_fileManager = new FileManager(resourcesPath);
    m_renderer = new GLRenderer();
    m_renderer->init(width, height);
}
GameController::~GameController()
{
    Log(LOG_INFO, "GameController", "Destroyed GameController");
    m_renderer->~GLRenderer();
}

void GameController::setRenderer(GLRenderer* r)
{
	this->m_renderer = r;
}
GLRenderer* GameController::getRenderer()
{
	return m_renderer;
}

void GameController::didRecieveInputEvent(InputType type, int locX, int locY)
{
	Log(LOG_EVENT, "GameController",  "DidRecieveInputEvent");
    m_fileManager->loadTextureFromFile("color");
}
<|endoftext|>


<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <cstdio>
#include "ir_print_visitor.h"
#include "glsl_types.h"

static void
print_type(const glsl_type *t)
{
   if (t->base_type == GLSL_TYPE_ARRAY) {
      printf("array (");
      print_type(t->fields.array);
      printf(") (%u))", t->length);
   } else if (t->base_type == GLSL_TYPE_STRUCT) {
      printf("struct (%s %u ", t->name ? t->name : "@", t->length);
      printf("(FINISHME: structure fields go here) ");
      printf(")");
   } else {
      printf("%s", t->name);
   }
}

void ir_print_visitor::visit(ir_variable *ir)
{
   if (deref_depth) {
      printf("(%s)", ir->name);
   } else {
      printf("(declare ");

      const char *const cent = (ir->centroid) ? "centroid " : "";
      const char *const inv = (ir->invariant) ? "invariant " : "";
      const char *const mode[] = { "", "uniform ", "in ", "out ", "inout " };
      const char *const interp[] = { "", "flat", "noperspective" };

      printf("(%s%s%s%s) ",
	     cent, inv, mode[ir->mode], interp[ir->interpolation]);

      printf("(");
      print_type(ir->type);
      printf(") ");
      printf("(%s)) ", ir->name);
   }
}

void ir_print_visitor::visit(ir_label *ir)
{
   printf("\n(label %s)", ir->label);
}

void ir_print_visitor::visit(ir_function_signature *ir)
{
   printf("%s:%d:\n", __func__, __LINE__);
   (void) ir;
}

void ir_print_visitor::visit(ir_function *ir)
{
   printf("(function %s\n", ir->name);
   printf(")\n");
}

void ir_print_visitor::visit(ir_expression *ir)
{
   printf("(expression ");

   printf("(FINISHME: operator) ");

   printf("(");
   if (ir->operands[0])
      ir->operands[0]->accept(this);
   printf(") ");

   printf("(");
   if (ir->operands[1])
      ir->operands[1]->accept(this);
   printf(")) ");
}

void ir_print_visitor::visit(ir_dereference *ir)
{
   deref_depth++;

   switch (ir->mode) {
   case ir_dereference::ir_reference_variable: {
      const unsigned swiz[4] = {
	 ir->selector.swizzle.x,
	 ir->selector.swizzle.y,
	 ir->selector.swizzle.z,
	 ir->selector.swizzle.w,
      };

      printf("(var_ref ");
      ir->var->accept(this);
      printf("(");
      for (unsigned i = 0; i < ir->selector.swizzle.num_components; i++) {
	 printf("%c", "xyzw"[swiz[i]]);
      }
      printf(")) ");
      break;
   }
   case ir_dereference::ir_reference_array:
      printf("(array_ref ");
      ir->var->accept(this);
      ir->selector.array_index->accept(this);
      printf(") ");
      break;
   case ir_dereference::ir_reference_record:
      printf("(record_ref ");
      ir->var->accept(this);
      printf("(%s)) ", ir->selector.field);
      break;
   }

   deref_depth--;
}

void ir_print_visitor::visit(ir_assignment *ir)
{
   printf("(assign (");

   if (ir->condition)
      ir->condition->accept(this);
   else
      printf("true");

   printf(") (");

   ir->lhs->accept(this);

   printf(") (");

   ir->rhs->accept(this);
   printf(") ");
}

void ir_print_visitor::visit(ir_constant *ir)
{
   (void) ir;

   printf("(constant (");
   print_type(ir->type);
   printf(") ");
   printf("(FINISHME: value goes here)");
   printf(") ");
}

void
ir_print_visitor::visit(ir_call *ir)
{
   (void) ir;

   printf("(call FINISHME: function name here\n");
   printf("    (FINISHME: function paramaters here))\n");
}

void
ir_print_visitor::visit(ir_return *ir)
{
   printf("(return");

   ir_expression *const value = ir->get_value();
   if (value) {
      printf(" ");
      value->accept(this);
   }

   printf(")");
}
<commit_msg>IR print visitor: Finish printing constants<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
#include <cstdio>
#include "ir_print_visitor.h"
#include "glsl_types.h"

static void
print_type(const glsl_type *t)
{
   if (t->base_type == GLSL_TYPE_ARRAY) {
      printf("array (");
      print_type(t->fields.array);
      printf(") (%u))", t->length);
   } else if (t->base_type == GLSL_TYPE_STRUCT) {
      printf("struct (%s %u ", t->name ? t->name : "@", t->length);
      printf("(FINISHME: structure fields go here) ");
      printf(")");
   } else {
      printf("%s", t->name);
   }
}

void ir_print_visitor::visit(ir_variable *ir)
{
   if (deref_depth) {
      printf("(%s)", ir->name);
   } else {
      printf("(declare ");

      const char *const cent = (ir->centroid) ? "centroid " : "";
      const char *const inv = (ir->invariant) ? "invariant " : "";
      const char *const mode[] = { "", "uniform ", "in ", "out ", "inout " };
      const char *const interp[] = { "", "flat", "noperspective" };

      printf("(%s%s%s%s) ",
	     cent, inv, mode[ir->mode], interp[ir->interpolation]);

      printf("(");
      print_type(ir->type);
      printf(") ");
      printf("(%s)) ", ir->name);
   }
}

void ir_print_visitor::visit(ir_label *ir)
{
   printf("\n(label %s)", ir->label);
}

void ir_print_visitor::visit(ir_function_signature *ir)
{
   printf("%s:%d:\n", __func__, __LINE__);
   (void) ir;
}

void ir_print_visitor::visit(ir_function *ir)
{
   printf("(function %s\n", ir->name);
   printf(")\n");
}

void ir_print_visitor::visit(ir_expression *ir)
{
   printf("(expression ");

   printf("(FINISHME: operator) ");

   printf("(");
   if (ir->operands[0])
      ir->operands[0]->accept(this);
   printf(") ");

   printf("(");
   if (ir->operands[1])
      ir->operands[1]->accept(this);
   printf(")) ");
}

void ir_print_visitor::visit(ir_dereference *ir)
{
   deref_depth++;

   switch (ir->mode) {
   case ir_dereference::ir_reference_variable: {
      const unsigned swiz[4] = {
	 ir->selector.swizzle.x,
	 ir->selector.swizzle.y,
	 ir->selector.swizzle.z,
	 ir->selector.swizzle.w,
      };

      printf("(var_ref ");
      ir->var->accept(this);
      printf("(");
      for (unsigned i = 0; i < ir->selector.swizzle.num_components; i++) {
	 printf("%c", "xyzw"[swiz[i]]);
      }
      printf(")) ");
      break;
   }
   case ir_dereference::ir_reference_array:
      printf("(array_ref ");
      ir->var->accept(this);
      ir->selector.array_index->accept(this);
      printf(") ");
      break;
   case ir_dereference::ir_reference_record:
      printf("(record_ref ");
      ir->var->accept(this);
      printf("(%s)) ", ir->selector.field);
      break;
   }

   deref_depth--;
}

void ir_print_visitor::visit(ir_assignment *ir)
{
   printf("(assign (");

   if (ir->condition)
      ir->condition->accept(this);
   else
      printf("true");

   printf(") (");

   ir->lhs->accept(this);

   printf(") (");

   ir->rhs->accept(this);
   printf(") ");
}

void ir_print_visitor::visit(ir_constant *ir)
{
   const glsl_type *const base_type = ir->type->get_base_type();

   printf("(constant (");
   print_type(base_type);
   printf(") ");

   const unsigned num_values = 1
      * ((ir->type->vector_elements > 0) ? ir->type->vector_elements : 1)
      * ((ir->type->matrix_columns > 0) ? ir->type->matrix_columns : 1);

   printf("(%d) (", num_values);
   for (unsigned i = 0; i < num_values; i++) {
      if (i != 0)
	 printf(", ");

      switch (base_type->base_type) {
      case GLSL_TYPE_UINT:  printf("%u", ir->value.u[i]); break;
      case GLSL_TYPE_INT:   printf("%d", ir->value.i[i]); break;
      case GLSL_TYPE_FLOAT: printf("%f", ir->value.f[i]); break;
      case GLSL_TYPE_BOOL:  printf("%d", ir->value.b[i]); break;
      default: assert(0);
      }
   }
   printf(")) ");
}

void
ir_print_visitor::visit(ir_call *ir)
{
   (void) ir;

   printf("(call FINISHME: function name here\n");
   printf("    (FINISHME: function paramaters here))\n");
}

void
ir_print_visitor::visit(ir_return *ir)
{
   printf("(return");

   ir_expression *const value = ir->get_value();
   if (value) {
      printf(" ");
      value->accept(this);
   }

   printf(")");
}
<|endoftext|>


<commit_before>#define PY_SSIZE_T_CLEAN 1
#include <Python.h>
#include <bytesobject.h>
#include <vector>
#include "../enc/encode.h"
#include "../dec/decode.h"
#include "../tools/version.h"

#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
#define PyInt_AsLong PyLong_AsLong
#endif

static PyObject *BrotliError;

static int as_bounded_int(PyObject *o, int* result, int lower_bound, int upper_bound) {
  long value = PyInt_AsLong(o);
  if ((value < (long) lower_bound) || (value > (long) upper_bound)) {
    return 0;
  }
  *result = (int) value;
  return 1;
}

static int mode_convertor(PyObject *o, BrotliEncoderMode *mode) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }

  int mode_value = -1;
  if (!as_bounded_int(o, &mode_value, 0, 255)) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }
  *mode = (BrotliEncoderMode) mode_value;
  if (*mode != BROTLI_MODE_GENERIC &&
      *mode != BROTLI_MODE_TEXT &&
      *mode != BROTLI_MODE_FONT) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }

  return 1;
}

static int quality_convertor(PyObject *o, int *quality) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid quality");
    return 0;
  }

  if (!as_bounded_int(o, quality, 0, 11)) {
    PyErr_SetString(BrotliError, "Invalid quality. Range is 0 to 11.");
    return 0;
  }

  return 1;
}

static int lgwin_convertor(PyObject *o, int *lgwin) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid lgwin");
    return 0;
  }

  if (!as_bounded_int(o, lgwin, 10, 24)) {
    PyErr_SetString(BrotliError, "Invalid lgwin. Range is 10 to 24.");
    return 0;
  }

  return 1;
}

static int lgblock_convertor(PyObject *o, int *lgblock) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid lgblock");
    return 0;
  }

  if (!as_bounded_int(o, lgblock, 0, 24) || (*lgblock != 0 && *lgblock < 16)) {
    PyErr_SetString(BrotliError, "Invalid lgblock. Can be 0 or in range 16 to 24.");
    return 0;
  }

  return 1;
}

PyDoc_STRVAR(compress__doc__,
"Compress a byte string.\n"
"\n"
"Signature:\n"
"  compress(string, mode=MODE_GENERIC, quality=11, lgwin=22, lgblock=0, dictionary='')\n"
"\n"
"Args:\n"
"  string (bytes): The input data.\n"
"  mode (int, optional): The compression mode can be MODE_GENERIC (default),\n"
"    MODE_TEXT (for UTF-8 format text input) or MODE_FONT (for WOFF 2.0). \n"
"  quality (int, optional): Controls the compression-speed vs compression-\n"
"    density tradeoff. The higher the quality, the slower the compression.\n"
"    Range is 0 to 11. Defaults to 11.\n"
"  lgwin (int, optional): Base 2 logarithm of the sliding window size. Range\n"
"    is 10 to 24. Defaults to 22.\n"
"  lgblock (int, optional): Base 2 logarithm of the maximum input block size.\n"
"    Range is 16 to 24. If set to 0, the value will be set based on the\n"
"    quality. Defaults to 0.\n"
"  dictionary (bytes, optional): Custom dictionary. Only last sliding window\n"
"     size bytes will be used.\n"
"\n"
"Returns:\n"
"  The compressed byte string.\n"
"\n"
"Raises:\n"
"  brotli.error: If arguments are invalid, or compressor fails.\n");

static PyObject* brotli_compress(PyObject *self, PyObject *args, PyObject *keywds) {
  PyObject *ret = NULL;
  uint8_t *input, *output = NULL, *custom_dictionary, *next_out;
  const uint8_t *next_in;
  size_t length, output_length, custom_dictionary_length, available_in, available_out;
  BrotliEncoderMode mode = (BrotliEncoderMode) -1;
  int quality = -1;
  int lgwin = -1;
  int lgblock = -1;
  int ok;

  static const char *kwlist[] = {
      "string", "mode", "quality", "lgwin", "lgblock", "dictionary", NULL};

  custom_dictionary = NULL;
  custom_dictionary_length = 0;

  ok = PyArg_ParseTupleAndKeywords(args, keywds, "s#|O&O&O&O&s#:compress",
                        const_cast<char **>(kwlist),
                        &input, &length,
                        &mode_convertor, &mode,
                        &quality_convertor, &quality,
                        &lgwin_convertor, &lgwin,
                        &lgblock_convertor, &lgblock,
                        &custom_dictionary, &custom_dictionary_length);
  if (!ok)
    return NULL;

  output_length = length + (length >> 2) + 10240;
  BrotliEncoderState* enc = BrotliEncoderCreateInstance(0, 0, 0);
  if (!enc) {
    ok = false;
    goto end;
  }
  output = new uint8_t[output_length];

  if ((int) mode != -1)
    BrotliEncoderSetParameter(enc, BROTLI_PARAM_MODE, (uint32_t)mode);
  if (quality != -1)
    BrotliEncoderSetParameter(enc, BROTLI_PARAM_QUALITY, (uint32_t)quality);
  if (lgwin != -1)
    BrotliEncoderSetParameter(enc, BROTLI_PARAM_LGWIN, (uint32_t)lgwin);
  if (lgblock != -1)
    BrotliEncoderSetParameter(enc, BROTLI_PARAM_LGBLOCK, (uint32_t)lgblock);

  if (custom_dictionary_length != 0) {
    BrotliEncoderSetCustomDictionary(enc, custom_dictionary_length,
                                     custom_dictionary);
  }
  available_out = output_length;
  next_out = output;
  available_in = length;
  next_in = input;
  BrotliEncoderCompressStream(enc, BROTLI_OPERATION_FINISH,
                              &available_in, &next_in,
                              &available_out, &next_out, 0);
  ok = BrotliEncoderIsFinished(enc);

end:
  BrotliEncoderDestroyInstance(enc);
  if (ok) {
    ret = PyBytes_FromStringAndSize((char*)output, output_length);
  } else {
    PyErr_SetString(BrotliError, "BrotliCompressBuffer failed");
  }

  delete[] output;

  return ret;
}

PyDoc_STRVAR(decompress__doc__,
"Decompress a compressed byte string.\n"
"\n"
"Signature:\n"
"  decompress(string)\n"
"\n"
"Args:\n"
"  string (bytes): The compressed input data.\n"
"  dictionary (bytes, optional): Custom dictionary. MUST be the same data\n"
"     as passed to compress method.\n"
"\n"
"Returns:\n"
"  The decompressed byte string.\n"
"\n"
"Raises:\n"
"  brotli.error: If decompressor fails.\n");

static PyObject* brotli_decompress(PyObject *self, PyObject *args, PyObject *keywds) {
  PyObject *ret = NULL;
  const uint8_t *input, *custom_dictionary;
  size_t length, custom_dictionary_length;
  int ok;

  static const char *kwlist[] = {"string", "dictionary", NULL};

  custom_dictionary = NULL;
  custom_dictionary_length = 0;

  ok = PyArg_ParseTupleAndKeywords(args, keywds, "s#|s#:decompress",
                        const_cast<char **>(kwlist),
                        &input, &length,
                        &custom_dictionary, &custom_dictionary_length);
  if (!ok)
    return NULL;

  std::vector<uint8_t> output;
  const size_t kBufferSize = 65536;
  uint8_t* buffer = new uint8_t[kBufferSize];
  BrotliState* state = BrotliCreateState(0, 0, 0);
  if (custom_dictionary_length != 0) {
    BrotliSetCustomDictionary(custom_dictionary_length, custom_dictionary, state);
  }

  BrotliResult result = BROTLI_RESULT_NEEDS_MORE_OUTPUT;
  while (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) {
    size_t available_out = kBufferSize;
    uint8_t* next_out = buffer;
    size_t total_out = 0;
    result = BrotliDecompressStream(&length, &input,
                                    &available_out, &next_out,
                                    &total_out, state);
    size_t used_out = kBufferSize - available_out;
    if (used_out != 0)
      output.insert(output.end(), buffer, buffer + used_out);
  }
  ok = result == BROTLI_RESULT_SUCCESS;
  if (ok) {
    ret = PyBytes_FromStringAndSize((char*)(output.size() ? &output[0] : NULL), output.size());
  } else {
    PyErr_SetString(BrotliError, "BrotliDecompress failed");
  }

  BrotliDestroyState(state);
  delete[] buffer;

  return ret;
}

static PyMethodDef brotli_methods[] = {
  {"compress",   (PyCFunction)brotli_compress, METH_VARARGS | METH_KEYWORDS, compress__doc__},
  {"decompress", (PyCFunction)brotli_decompress, METH_VARARGS | METH_KEYWORDS, decompress__doc__},
  {NULL, NULL, 0, NULL}
};

PyDoc_STRVAR(brotli__doc__,
"The functions in this module allow compression and decompression using the\n"
"Brotli library.\n\n");

#if PY_MAJOR_VERSION >= 3
#define INIT_BROTLI   PyInit_brotli
#define CREATE_BROTLI PyModule_Create(&brotli_module)
#define RETURN_BROTLI return m

static struct PyModuleDef brotli_module = {
  PyModuleDef_HEAD_INIT,
  "brotli",
  brotli__doc__,
  0,
  brotli_methods,
  NULL,
  NULL,
  NULL
};
#else
#define INIT_BROTLI   initbrotli
#define CREATE_BROTLI Py_InitModule3("brotli", brotli_methods, brotli__doc__)
#define RETURN_BROTLI return
#endif

PyMODINIT_FUNC INIT_BROTLI(void) {
  PyObject *m = CREATE_BROTLI;

  BrotliError = PyErr_NewException((char*) "brotli.error", NULL, NULL);

  if (BrotliError != NULL) {
    Py_INCREF(BrotliError);
    PyModule_AddObject(m, "error", BrotliError);
  }

  PyModule_AddIntConstant(m, "MODE_GENERIC", (int) BROTLI_MODE_GENERIC);
  PyModule_AddIntConstant(m, "MODE_TEXT", (int) BROTLI_MODE_TEXT);
  PyModule_AddIntConstant(m, "MODE_FONT", (int) BROTLI_MODE_FONT);

  PyModule_AddStringConstant(m, "__version__", BROTLI_VERSION);

  RETURN_BROTLI;
}
<commit_msg>Fix issue #383<commit_after>#define PY_SSIZE_T_CLEAN 1
#include <Python.h>
#include <bytesobject.h>
#include <vector>
#include "../enc/encode.h"
#include "../dec/decode.h"
#include "../tools/version.h"

#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
#define PyInt_AsLong PyLong_AsLong
#endif

static PyObject *BrotliError;

static int as_bounded_int(PyObject *o, int* result, int lower_bound, int upper_bound) {
  long value = PyInt_AsLong(o);
  if ((value < (long) lower_bound) || (value > (long) upper_bound)) {
    return 0;
  }
  *result = (int) value;
  return 1;
}

static int mode_convertor(PyObject *o, BrotliEncoderMode *mode) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }

  int mode_value = -1;
  if (!as_bounded_int(o, &mode_value, 0, 255)) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }
  *mode = (BrotliEncoderMode) mode_value;
  if (*mode != BROTLI_MODE_GENERIC &&
      *mode != BROTLI_MODE_TEXT &&
      *mode != BROTLI_MODE_FONT) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }

  return 1;
}

static int quality_convertor(PyObject *o, int *quality) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid quality");
    return 0;
  }

  if (!as_bounded_int(o, quality, 0, 11)) {
    PyErr_SetString(BrotliError, "Invalid quality. Range is 0 to 11.");
    return 0;
  }

  return 1;
}

static int lgwin_convertor(PyObject *o, int *lgwin) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid lgwin");
    return 0;
  }

  if (!as_bounded_int(o, lgwin, 10, 24)) {
    PyErr_SetString(BrotliError, "Invalid lgwin. Range is 10 to 24.");
    return 0;
  }

  return 1;
}

static int lgblock_convertor(PyObject *o, int *lgblock) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid lgblock");
    return 0;
  }

  if (!as_bounded_int(o, lgblock, 0, 24) || (*lgblock != 0 && *lgblock < 16)) {
    PyErr_SetString(BrotliError, "Invalid lgblock. Can be 0 or in range 16 to 24.");
    return 0;
  }

  return 1;
}

PyDoc_STRVAR(compress__doc__,
"Compress a byte string.\n"
"\n"
"Signature:\n"
"  compress(string, mode=MODE_GENERIC, quality=11, lgwin=22, lgblock=0, dictionary='')\n"
"\n"
"Args:\n"
"  string (bytes): The input data.\n"
"  mode (int, optional): The compression mode can be MODE_GENERIC (default),\n"
"    MODE_TEXT (for UTF-8 format text input) or MODE_FONT (for WOFF 2.0). \n"
"  quality (int, optional): Controls the compression-speed vs compression-\n"
"    density tradeoff. The higher the quality, the slower the compression.\n"
"    Range is 0 to 11. Defaults to 11.\n"
"  lgwin (int, optional): Base 2 logarithm of the sliding window size. Range\n"
"    is 10 to 24. Defaults to 22.\n"
"  lgblock (int, optional): Base 2 logarithm of the maximum input block size.\n"
"    Range is 16 to 24. If set to 0, the value will be set based on the\n"
"    quality. Defaults to 0.\n"
"  dictionary (bytes, optional): Custom dictionary. Only last sliding window\n"
"     size bytes will be used.\n"
"\n"
"Returns:\n"
"  The compressed byte string.\n"
"\n"
"Raises:\n"
"  brotli.error: If arguments are invalid, or compressor fails.\n");

static PyObject* brotli_compress(PyObject *self, PyObject *args, PyObject *keywds) {
  PyObject *ret = NULL;
  uint8_t *input, *output = NULL, *custom_dictionary, *next_out;
  const uint8_t *next_in;
  size_t length, output_length, custom_dictionary_length, available_in, available_out;
  BrotliEncoderMode mode = (BrotliEncoderMode) -1;
  int quality = -1;
  int lgwin = -1;
  int lgblock = -1;
  int ok;

  static const char *kwlist[] = {
      "string", "mode", "quality", "lgwin", "lgblock", "dictionary", NULL};

  custom_dictionary = NULL;
  custom_dictionary_length = 0;

  ok = PyArg_ParseTupleAndKeywords(args, keywds, "s#|O&O&O&O&s#:compress",
                        const_cast<char **>(kwlist),
                        &input, &length,
                        &mode_convertor, &mode,
                        &quality_convertor, &quality,
                        &lgwin_convertor, &lgwin,
                        &lgblock_convertor, &lgblock,
                        &custom_dictionary, &custom_dictionary_length);
  if (!ok)
    return NULL;

  output_length = length + (length >> 2) + 10240;
  BrotliEncoderState* enc = BrotliEncoderCreateInstance(0, 0, 0);
  if (!enc) {
    ok = false;
    goto end;
  }
  output = new uint8_t[output_length];

  if ((int) mode != -1)
    BrotliEncoderSetParameter(enc, BROTLI_PARAM_MODE, (uint32_t)mode);
  if (quality != -1)
    BrotliEncoderSetParameter(enc, BROTLI_PARAM_QUALITY, (uint32_t)quality);
  if (lgwin != -1)
    BrotliEncoderSetParameter(enc, BROTLI_PARAM_LGWIN, (uint32_t)lgwin);
  if (lgblock != -1)
    BrotliEncoderSetParameter(enc, BROTLI_PARAM_LGBLOCK, (uint32_t)lgblock);

  if (custom_dictionary_length != 0) {
    BrotliEncoderSetCustomDictionary(enc, custom_dictionary_length,
                                     custom_dictionary);
  }
  available_out = output_length;
  next_out = output;
  available_in = length;
  next_in = input;
  BrotliEncoderCompressStream(enc, BROTLI_OPERATION_FINISH,
                              &available_in, &next_in,
                              &available_out, &next_out, 0);
  ok = BrotliEncoderIsFinished(enc);

end:
  BrotliEncoderDestroyInstance(enc);
  if (ok) {
    ret = PyBytes_FromStringAndSize((char*)output, output_length - available_out);
  } else {
    PyErr_SetString(BrotliError, "BrotliCompressBuffer failed");
  }

  delete[] output;

  return ret;
}

PyDoc_STRVAR(decompress__doc__,
"Decompress a compressed byte string.\n"
"\n"
"Signature:\n"
"  decompress(string)\n"
"\n"
"Args:\n"
"  string (bytes): The compressed input data.\n"
"  dictionary (bytes, optional): Custom dictionary. MUST be the same data\n"
"     as passed to compress method.\n"
"\n"
"Returns:\n"
"  The decompressed byte string.\n"
"\n"
"Raises:\n"
"  brotli.error: If decompressor fails.\n");

static PyObject* brotli_decompress(PyObject *self, PyObject *args, PyObject *keywds) {
  PyObject *ret = NULL;
  const uint8_t *input, *custom_dictionary;
  size_t length, custom_dictionary_length;
  int ok;

  static const char *kwlist[] = {"string", "dictionary", NULL};

  custom_dictionary = NULL;
  custom_dictionary_length = 0;

  ok = PyArg_ParseTupleAndKeywords(args, keywds, "s#|s#:decompress",
                        const_cast<char **>(kwlist),
                        &input, &length,
                        &custom_dictionary, &custom_dictionary_length);
  if (!ok)
    return NULL;

  std::vector<uint8_t> output;
  const size_t kBufferSize = 65536;
  uint8_t* buffer = new uint8_t[kBufferSize];
  BrotliState* state = BrotliCreateState(0, 0, 0);
  if (custom_dictionary_length != 0) {
    BrotliSetCustomDictionary(custom_dictionary_length, custom_dictionary, state);
  }

  BrotliResult result = BROTLI_RESULT_NEEDS_MORE_OUTPUT;
  while (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) {
    size_t available_out = kBufferSize;
    uint8_t* next_out = buffer;
    size_t total_out = 0;
    result = BrotliDecompressStream(&length, &input,
                                    &available_out, &next_out,
                                    &total_out, state);
    size_t used_out = kBufferSize - available_out;
    if (used_out != 0)
      output.insert(output.end(), buffer, buffer + used_out);
  }
  ok = result == BROTLI_RESULT_SUCCESS;
  if (ok) {
    ret = PyBytes_FromStringAndSize((char*)(output.size() ? &output[0] : NULL), output.size());
  } else {
    PyErr_SetString(BrotliError, "BrotliDecompress failed");
  }

  BrotliDestroyState(state);
  delete[] buffer;

  return ret;
}

static PyMethodDef brotli_methods[] = {
  {"compress",   (PyCFunction)brotli_compress, METH_VARARGS | METH_KEYWORDS, compress__doc__},
  {"decompress", (PyCFunction)brotli_decompress, METH_VARARGS | METH_KEYWORDS, decompress__doc__},
  {NULL, NULL, 0, NULL}
};

PyDoc_STRVAR(brotli__doc__,
"The functions in this module allow compression and decompression using the\n"
"Brotli library.\n\n");

#if PY_MAJOR_VERSION >= 3
#define INIT_BROTLI   PyInit_brotli
#define CREATE_BROTLI PyModule_Create(&brotli_module)
#define RETURN_BROTLI return m

static struct PyModuleDef brotli_module = {
  PyModuleDef_HEAD_INIT,
  "brotli",
  brotli__doc__,
  0,
  brotli_methods,
  NULL,
  NULL,
  NULL
};
#else
#define INIT_BROTLI   initbrotli
#define CREATE_BROTLI Py_InitModule3("brotli", brotli_methods, brotli__doc__)
#define RETURN_BROTLI return
#endif

PyMODINIT_FUNC INIT_BROTLI(void) {
  PyObject *m = CREATE_BROTLI;

  BrotliError = PyErr_NewException((char*) "brotli.error", NULL, NULL);

  if (BrotliError != NULL) {
    Py_INCREF(BrotliError);
    PyModule_AddObject(m, "error", BrotliError);
  }

  PyModule_AddIntConstant(m, "MODE_GENERIC", (int) BROTLI_MODE_GENERIC);
  PyModule_AddIntConstant(m, "MODE_TEXT", (int) BROTLI_MODE_TEXT);
  PyModule_AddIntConstant(m, "MODE_FONT", (int) BROTLI_MODE_FONT);

  PyModule_AddStringConstant(m, "__version__", BROTLI_VERSION);

  RETURN_BROTLI;
}
<|endoftext|>


<commit_before>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2011 Emmanuel Benazera <ebenazer@seeks-project.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 **/

#define _PCREPOSIX_H // avoid pcreposix.h conflict with regex.h used by gtest
#include <gtest/gtest.h>

#include "query_context.h"
#include "websearch.h"
#include "websearch_configuration.h"
#include "errlog.h"

using namespace seeks_plugins;
using sp::errlog;

class QCTest : public testing::Test
{
  protected:
    virtual void SetUp()
    {
      errlog::init_log_module();
      errlog::set_debug_level(LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO | LOG_LEVEL_DEBUG);
      websearch::_wconfig = new websearch_configuration("");
      websearch::_wconfig->_se_connect_timeout = 1;
      websearch::_wconfig->_se_transfer_timeout = 1;
      websearch::_wconfig->_se_enabled = feeds("dummy","url1");
    }

    virtual void TearDown()
    {
      delete websearch::_wconfig;
    }
};

TEST_F(QCTest,expand_no_engine_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> parameters;
  feeds engines;
  int code = SP_ERR_OK;
  try
    {
      qc.expand(&csp,&rsp,&parameters,0,1,engines);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE,code);
}

TEST_F(QCTest,expand_no_engine_output_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> parameters;
  miscutil::add_map_entry(&parameters,"q",1,"test",1);
  miscutil::add_map_entry(&parameters,"expansion",1,"",1);
  feeds engines("dummy","URL1");
  int code = SP_ERR_OK;
  try
    {
      qc.expand(&csp,&rsp,&parameters,0,1,engines);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE_OUTPUT,code);
}

TEST_F(QCTest,generate_expansion_param_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> parameters;
  bool expanded = false;
  int code = SP_ERR_OK;
  try
    {
      qc.generate(&csp,&rsp,&parameters,expanded);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(SP_ERR_CGI_PARAMS,code);
}

TEST_F(QCTest,generate_wrong_expansion_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>();
  miscutil::add_map_entry(parameters,"q",1,"test",1);
  miscutil::add_map_entry(parameters,"expansion",1,"bla",1);
  bool expanded = false;
  int code = SP_ERR_OK;
  try
    {
      qc.generate(&csp,&rsp,parameters,expanded);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(SP_ERR_CGI_PARAMS,code);
  miscutil::free_map(parameters);
}

TEST_F(QCTest,generate_no_engine_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>();
  miscutil::add_map_entry(parameters,"q",1,"test",1);
  miscutil::add_map_entry(parameters,"expansion",1,"1",1);
  miscutil::add_map_entry(parameters,"engines",1,"",1);
  bool expanded = false;
  int code = SP_ERR_OK;
  try
    {
      qc.generate(&csp,&rsp,parameters,expanded);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE,code);
  miscutil::free_map(parameters);
}

TEST_F(QCTest,generate_no_engine_output_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>();
  miscutil::add_map_entry(parameters,"q",1,"test",1);
  miscutil::add_map_entry(parameters,"expansion",1,"1",1);
  miscutil::add_map_entry(parameters,"engines",1,"dummy",1);
  bool expanded = false;
  int code = SP_ERR_OK;
  try
    {
      qc.generate(&csp,&rsp,parameters,expanded);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE_OUTPUT,code);
  miscutil::free_map(parameters);
}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>fixed memory cleanup in qc unit tests<commit_after>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2011 Emmanuel Benazera <ebenazer@seeks-project.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 **/

#define _PCREPOSIX_H // avoid pcreposix.h conflict with regex.h used by gtest
#include <gtest/gtest.h>

#include "query_context.h"
#include "websearch.h"
#include "websearch_configuration.h"
#include "se_handler.h"
#include "errlog.h"

using namespace seeks_plugins;
using sp::errlog;

class QCTest : public testing::Test
{
  protected:
    virtual void SetUp()
    {
      errlog::init_log_module();
      errlog::set_debug_level(LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO | LOG_LEVEL_DEBUG);
      websearch::_wconfig = new websearch_configuration("");
      websearch::_wconfig->_se_connect_timeout = 1;
      websearch::_wconfig->_se_transfer_timeout = 1;
      websearch::_wconfig->_se_enabled = feeds("dummy","url1");
    }

    virtual void TearDown()
    {
      delete websearch::_wconfig;
    }
};

TEST_F(QCTest,expand_no_engine_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>();
  feeds engines;
  int code = SP_ERR_OK;
  try
    {
      qc.expand(&csp,&rsp,parameters,0,1,engines);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE,code);
  miscutil::free_map(parameters);
}

TEST_F(QCTest,expand_no_engine_output_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>();
  miscutil::add_map_entry(parameters,"q",1,"test",1);
  miscutil::add_map_entry(parameters,"expansion",1,"",1);
  feeds engines("dummy","URL1");
  int code = SP_ERR_OK;
  try
    {
      qc.expand(&csp,&rsp,parameters,0,1,engines);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE_OUTPUT,code);
  miscutil::free_map(parameters);
}

TEST_F(QCTest,generate_expansion_param_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>();
  bool expanded = false;
  int code = SP_ERR_OK;
  try
    {
      qc.generate(&csp,&rsp,parameters,expanded);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(SP_ERR_CGI_PARAMS,code);
  miscutil::free_map(parameters);
}

TEST_F(QCTest,generate_wrong_expansion_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>();
  miscutil::add_map_entry(parameters,"q",1,"test",1);
  miscutil::add_map_entry(parameters,"expansion",1,"bla",1);
  bool expanded = false;
  int code = SP_ERR_OK;
  try
    {
      qc.generate(&csp,&rsp,parameters,expanded);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(SP_ERR_CGI_PARAMS,code);
  miscutil::free_map(parameters);
}

TEST_F(QCTest,generate_no_engine_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>();
  miscutil::add_map_entry(parameters,"q",1,"test",1);
  miscutil::add_map_entry(parameters,"expansion",1,"1",1);
  miscutil::add_map_entry(parameters,"engines",1,"",1);
  bool expanded = false;
  int code = SP_ERR_OK;
  try
    {
      qc.generate(&csp,&rsp,parameters,expanded);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE,code);
  miscutil::free_map(parameters);
}

TEST_F(QCTest,generate_no_engine_output_fail)
{
  query_context qc;
  client_state csp;
  http_response rsp;
  hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters
  = new hash_map<const char*,const char*,hash<const char*>,eqstr>();
  miscutil::add_map_entry(parameters,"q",1,"test",1);
  miscutil::add_map_entry(parameters,"expansion",1,"1",1);
  miscutil::add_map_entry(parameters,"engines",1,"dummy",1);
  bool expanded = false;
  int code = SP_ERR_OK;
  try
    {
      qc.generate(&csp,&rsp,parameters,expanded);
    }
  catch (sp_exception &e)
    {
      code = e.code();
    }
  ASSERT_EQ(WB_ERR_NO_ENGINE_OUTPUT,code);
  se_handler::cleanup_handlers();
  miscutil::free_map(parameters);
}

int main(int argc, char **argv)
{
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


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

#include <sauce/sauce.h>

using ::sauce::Binder;

namespace sauce {
namespace test {

struct C {};
struct D {};

struct Singleton {
  bool operator==(Singleton const & other) {
    return this == &other;
  }
};

struct Session {
  bool operator==(Session const & other) {
    return this == &other;
  }
};

struct Request {
  bool operator==(Request const & other) {
    return this == &other;
  }
};

struct MyScope {};

void ScopedModule(Binder & binder) {
  binder.bind<Singleton>().in<SingletonScope>().to<Singleton()>();
  binder.bind<Session>().in<SessionScope>().to<Session()>();
  binder.bind<Request>().in<RequestScope>().to<Request()>();
  binder.bind<C>().in<MyScope>().to<C()>();
  binder.bind<D>().to<D()>();
}

struct ScopeTest:
  public ::testing::Test {

  Modules modules;
  SAUCE_SHARED_PTR<Injector> injector;

  ScopeTest():
    modules(),
    injector() {}

  virtual void SetUp() {
    modules.add(&ScopedModule);
    injector = modules.createInjector();
  }
};

TEST_F(ScopeTest, shouldScopeSingletonDependenciesByDefault) {
  SAUCE_SHARED_PTR<Singleton> aSingleton;
  SAUCE_SHARED_PTR<Singleton> theSameSingleton;
  SAUCE_SHARED_PTR<Singleton> aNewSingleton;

  {
    SAUCE_SHARED_PTR<Injector> singletonScoped(modules.createInjector());
    aSingleton = singletonScoped->get<Singleton>();
    theSameSingleton = singletonScoped->get<Singleton>();
  }
  EXPECT_EQ(aSingleton, theSameSingleton);

  {
    SAUCE_SHARED_PTR<Injector> singletonScoped(modules.createInjector());
    aNewSingleton = singletonScoped->get<Singleton>();
  }
  EXPECT_NE(aSingleton, aNewSingleton);
}

TEST_F(ScopeTest, shouldScopeSessionDependenciesIfAsked) {
  SAUCE_SHARED_PTR<Session> aSession;
  SAUCE_SHARED_PTR<Session> theSameSession;
  SAUCE_SHARED_PTR<Session> aNewSession;

  {
    SAUCE_SHARED_PTR<Injector> sessionScoped = injector->enter<SessionScope>();
    aSession = sessionScoped->get<Session>();
    theSameSession = sessionScoped->get<Session>();
  }
  EXPECT_EQ(aSession, theSameSession);

  {
    SAUCE_SHARED_PTR<Injector> sessionScoped = injector->enter<SessionScope>();
    aNewSession = sessionScoped->get<Session>();
  }
  EXPECT_NE(aSession, aNewSession);
}

TEST_F(ScopeTest, shouldScopeRequestDependenciesIfAsked) {
  SAUCE_SHARED_PTR<Request> aRequest;
  SAUCE_SHARED_PTR<Request> theSameRequest;
  SAUCE_SHARED_PTR<Request> aNewRequest;

  {
    SAUCE_SHARED_PTR<Injector> requestScoped = injector->enter<RequestScope>();
    aRequest = requestScoped->get<Request>();
    theSameRequest = requestScoped->get<Request>();
  }
  EXPECT_EQ(aRequest, theSameRequest);

  {
    SAUCE_SHARED_PTR<Injector> requestScoped = injector->enter<RequestScope>();
    aNewRequest = requestScoped->get<Request>();
  }
  EXPECT_NE(aRequest, aNewRequest);
}

TEST_F(ScopeTest, shouldScopeCustomScopedDependenciesIfAsked) {
  SAUCE_SHARED_PTR<C> aC;
  SAUCE_SHARED_PTR<C> theSameC;
  SAUCE_SHARED_PTR<C> aNewC;

  {
    SAUCE_SHARED_PTR<Injector> scoped = injector->enter<RequestScope>();
    aC = scoped->get<C>();
    theSameC = scoped->get<C>();
  }
  EXPECT_EQ(aC, theSameC);

  {
    SAUCE_SHARED_PTR<Injector> scoped = injector->enter<RequestScope>();
    aNewC = scoped->get<C>();
  }
  EXPECT_NE(aC, aNewC);
}

// TEST_F(ScopeTest, shouldNestScopes) {}

TEST_F(ScopeTest, shouldNotScopeUnscopedDependencies) {
  SAUCE_SHARED_PTR<D> aD = injector->get<D>();
  SAUCE_SHARED_PTR<D> aNewD = injector->get<D>();
  EXPECT_NE(aD, aNewD);
}

struct CrankyConstructorException: public std::runtime_error {
  CrankyConstructorException():
    std::runtime_error("Can't connect to something-er-other!") {}
};

struct CrankyConstructor {
  CrankyConstructor() {
    throw CrankyConstructorException();
  }
};

void EagerlyScopedModule(Binder & binder) {
  binder.bind<CrankyConstructor>().in<RequestScope>().to<CrankyConstructor()>();
}

struct EagerlyScopeTest:
  public ::testing::Test {

  SAUCE_SHARED_PTR<Injector> injector;

  EagerlyScopeTest():
    injector(Modules().add(&EagerlyScopedModule).createInjector()) {}
};

TEST_F(EagerlyScopeTest, shouldProvidedScopedDependenciesEagerlyIfAsked) {
  SAUCE_SHARED_PTR<Injector> requestScoped = injector->enter<RequestScope>();
  ASSERT_THROW(requestScoped->eagerlyProvide<RequestScope>(), CrankyConstructorException);
}

}
}
<commit_msg>Prove nested scopes are broken.<commit_after>#include <gtest/gtest.h>

#include <sauce/sauce.h>

using ::sauce::Binder;

namespace sauce {
namespace test {

struct C {};
struct D {};

struct Singleton {
  bool operator==(Singleton const & other) {
    return this == &other;
  }
};

struct Session {
  bool operator==(Session const & other) {
    return this == &other;
  }
};

struct Request {
  bool operator==(Request const & other) {
    return this == &other;
  }
};

struct MyScope {};

void ScopedModule(Binder & binder) {
  binder.bind<Singleton>().in<SingletonScope>().to<Singleton()>();
  binder.bind<Session>().in<SessionScope>().to<Session()>();
  binder.bind<Request>().in<RequestScope>().to<Request()>();
  binder.bind<C>().in<MyScope>().to<C()>();
  binder.bind<D>().to<D()>();
}

struct ScopeTest:
  public ::testing::Test {

  Modules modules;
  SAUCE_SHARED_PTR<Injector> injector;

  ScopeTest():
    modules(),
    injector() {}

  virtual void SetUp() {
    modules.add(&ScopedModule);
    injector = modules.createInjector();
  }
};

TEST_F(ScopeTest, shouldScopeSingletonDependenciesByDefault) {
  SAUCE_SHARED_PTR<Singleton> aSingleton;
  SAUCE_SHARED_PTR<Singleton> theSameSingleton;
  SAUCE_SHARED_PTR<Singleton> aNewSingleton;

  {
    SAUCE_SHARED_PTR<Injector> singletonScoped(modules.createInjector());
    aSingleton = singletonScoped->get<Singleton>();
    theSameSingleton = singletonScoped->get<Singleton>();
  }
  EXPECT_EQ(aSingleton, theSameSingleton);

  {
    SAUCE_SHARED_PTR<Injector> singletonScoped(modules.createInjector());
    aNewSingleton = singletonScoped->get<Singleton>();
  }
  EXPECT_NE(aSingleton, aNewSingleton);
}

TEST_F(ScopeTest, shouldScopeSessionDependenciesIfAsked) {
  SAUCE_SHARED_PTR<Session> aSession;
  SAUCE_SHARED_PTR<Session> theSameSession;
  SAUCE_SHARED_PTR<Session> aNewSession;

  {
    SAUCE_SHARED_PTR<Injector> sessionScoped = injector->enter<SessionScope>();
    aSession = sessionScoped->get<Session>();
    theSameSession = sessionScoped->get<Session>();
  }
  EXPECT_EQ(aSession, theSameSession);

  {
    SAUCE_SHARED_PTR<Injector> sessionScoped = injector->enter<SessionScope>();
    aNewSession = sessionScoped->get<Session>();
  }
  EXPECT_NE(aSession, aNewSession);
}

TEST_F(ScopeTest, shouldScopeRequestDependenciesIfAsked) {
  SAUCE_SHARED_PTR<Request> aRequest;
  SAUCE_SHARED_PTR<Request> theSameRequest;
  SAUCE_SHARED_PTR<Request> aNewRequest;

  {
    SAUCE_SHARED_PTR<Injector> requestScoped = injector->enter<RequestScope>();
    aRequest = requestScoped->get<Request>();
    theSameRequest = requestScoped->get<Request>();
  }
  EXPECT_EQ(aRequest, theSameRequest);

  {
    SAUCE_SHARED_PTR<Injector> requestScoped = injector->enter<RequestScope>();
    aNewRequest = requestScoped->get<Request>();
  }
  EXPECT_NE(aRequest, aNewRequest);
}

TEST_F(ScopeTest, shouldScopeCustomScopedDependenciesIfAsked) {
  SAUCE_SHARED_PTR<C> aC;
  SAUCE_SHARED_PTR<C> theSameC;
  SAUCE_SHARED_PTR<C> aNewC;

  {
    SAUCE_SHARED_PTR<Injector> scoped = injector->enter<RequestScope>();
    aC = scoped->get<C>();
    theSameC = scoped->get<C>();
  }
  EXPECT_EQ(aC, theSameC);

  {
    SAUCE_SHARED_PTR<Injector> scoped = injector->enter<RequestScope>();
    aNewC = scoped->get<C>();
  }
  EXPECT_NE(aC, aNewC);
}

TEST_F(ScopeTest, shouldNestScopes) {
  SAUCE_SHARED_PTR<Singleton> aSingleton = injector->get<Singleton>();
  SAUCE_SHARED_PTR<Singleton> theSameSingleton;

  {
    SAUCE_SHARED_PTR<Injector> sessionScoped = injector->enter<SessionScope>();
    theSameSingleton = sessionScoped->get<Singleton>();
  }

  // EXPECT_EQ(aSingleton, theSameSingleton);
}

TEST_F(ScopeTest, shouldNotScopeUnscopedDependencies) {
  SAUCE_SHARED_PTR<D> aD = injector->get<D>();
  SAUCE_SHARED_PTR<D> aNewD = injector->get<D>();
  EXPECT_NE(aD, aNewD);
}

struct CrankyConstructorException: public std::runtime_error {
  CrankyConstructorException():
    std::runtime_error("Can't connect to something-er-other!") {}
};

struct CrankyConstructor {
  CrankyConstructor() {
    throw CrankyConstructorException();
  }
};

void EagerlyScopedModule(Binder & binder) {
  binder.bind<CrankyConstructor>().in<RequestScope>().to<CrankyConstructor()>();
}

struct EagerlyScopeTest:
  public ::testing::Test {

  SAUCE_SHARED_PTR<Injector> injector;

  EagerlyScopeTest():
    injector(Modules().add(&EagerlyScopedModule).createInjector()) {}
};

TEST_F(EagerlyScopeTest, shouldProvidedScopedDependenciesEagerlyIfAsked) {
  SAUCE_SHARED_PTR<Injector> requestScoped = injector->enter<RequestScope>();
  ASSERT_THROW(requestScoped->eagerlyProvide<RequestScope>(), CrankyConstructorException);
}

}
}
<|endoftext|>


<commit_before>#include "Grid.h"

#include <cassert>
#include "Tile.h"

int Grid::getWidth()
{
    return -1;
}

int Grid::getHeight()
{
    return -1;
}

namespace
{
#ifdef DEBUG
    void assertGridIsRectangular(std::list<std::list<bool>*>& tiles)
    {
        //check the grid is rectangular and not jagged
        //i.e. all sublists are the same size
        //note that the number of sublists does not have to be equal to the number of columns
        for(std::list<bool>* thisSubList : tiles)
        {
            for(std::list<bool>* otherSubList : tiles)
            {
                assert(thisSubList->size() == otherSubList->size());
            }
        }
    }
#endif
}

void Grid::expandGrid()
{
    //check the grid is the right shape before and after we modify it
#ifdef DEBUG
    assertGridIsRectangular(tiles);
#endif
    const int newWidth = getWidth() + 1;
    const int newHeight = getHeight() + 1;

    //add 1 tile to the beginning of each sublist (prepending a column)
    //add 1 tile to the end of each sublist (appending a column)
    for(std::list<bool>* thisSubList : tiles)
    {
        thisSubList->push_front(TILE_DEAD);
        thisSubList->push_back(TILE_DEAD);
    }

    //add 1 row to the beginning of the tiles list (prepending a row)
    //add 1 row to the end of the tiles list (appending a column)
    std::list<bool> *firstList = new std::list<bool>(newWidth, TILE_DEAD),
        *lastList = new std::list<bool>(newWidth, TILE_DEAD);
    tiles.push_front(firstList);
    tiles.push_back(lastList);

#ifdef DEBUG
    //check the size is correct
    assertGridIsRectangular(tiles);
#endif
}

bool Grid::touchingEdges()
{
    //TODO: IMPLEMENT
    return true;
}

Grid::Grid(const Grid& other)
{
    //TODO: IMPLEMENT
}

Grid::Grid(const int width, const int height)
{
    for(int i = 0; i < height; i++)
    {
        //don't have to loop to add items to the list
        //this list CTOR will insert <width> number of bools all at once
        std::list<bool>* subList = new std::list<bool>(width, TILE_DEAD);
        //insert the sublist
        tiles.push_back(subList);
    }
}

Grid::~Grid()
{
    for(std::list<bool>* thisSubList : tiles)
    {
        delete thisSubList;
    }
}
<commit_msg>implemented getWidth and getHeight added sanity checks<commit_after>#include "Grid.h"

#include <cassert>
#include "Tile.h"

int Grid::getWidth()
{
#ifdef DEBUG
    assertGridIsRectangular(tiles);
#endif
    return tiles.front()->size();
}

int Grid::getHeight()
{
#ifdef DEBUG
    assertGridIsRectangular(tiles);
#endif
    return tiles.size();
}

namespace
{
#ifdef DEBUG
    void assertGridIsRectangular(std::list<std::list<bool>*>& tiles)
    {
        //sanity check
        assert(!tiles.empty());

        //check the grid is rectangular and not jagged
        //i.e. all sublists are the same size
        //note that the number of sublists does not have to be equal to the number of columns
        for(std::list<bool>* thisSubList : tiles)
        {
            for(std::list<bool>* otherSubList : tiles)
            {
                assert(!otherSubList.empty());
                assert(thisSubList->size() == otherSubList->size());
            }
        }
    }
#endif
}

void Grid::expandGrid()
{
    //check the grid is the right shape before and after we modify it
#ifdef DEBUG
    assertGridIsRectangular(tiles);
#endif
    const int newWidth = getWidth() + 1;
    const int newHeight = getHeight() + 1;

    //add 1 tile to the beginning of each sublist (prepending a column)
    //add 1 tile to the end of each sublist (appending a column)
    for(std::list<bool>* thisSubList : tiles)
    {
        thisSubList->push_front(TILE_DEAD);
        thisSubList->push_back(TILE_DEAD);
    }

    //add 1 row to the beginning of the tiles list (prepending a row)
    //add 1 row to the end of the tiles list (appending a column)
    std::list<bool> *firstList = new std::list<bool>(newWidth, TILE_DEAD),
        *lastList = new std::list<bool>(newWidth, TILE_DEAD);
    tiles.push_front(firstList);
    tiles.push_back(lastList);

#ifdef DEBUG
    //check the size is correct
    assertGridIsRectangular(tiles);
#endif
}

bool Grid::touchingEdges()
{
    //TODO: IMPLEMENT
    return true;
}

Grid::Grid(const Grid& other)
{
    //TODO: IMPLEMENT
}

Grid::Grid(const int width, const int height)
{
    for(int i = 0; i < height; i++)
    {
        //don't have to loop to add items to the list
        //this list CTOR will insert <width> number of bools all at once
        std::list<bool>* subList = new std::list<bool>(width, TILE_DEAD);
        //insert the sublist
        tiles.push_back(subList);
    }
}

Grid::~Grid()
{
    for(std::list<bool>* thisSubList : tiles)
    {
        delete thisSubList;
    }
}
<|endoftext|>