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

#include "settings.h"
#include <QSettings>
#include <QDir>

#define PATH QString("%1%2.config%2/cameraplus.conf").arg(QDir::homePath()).arg(QDir::separator())

#define DEFAULT_MODE               0
#define DEFAULT_SCENE_MODE         6 // Auto
#define DEFAULT_TIMEOUT            0
#define DEFAULT_USE_GPS            true
#define DEFAULT_USE_GEOTAGS        true
#define DEFAULT_COLOR_FILTER       0
#define DEFAULT_WHITE_BALANCE      0
#define DEFAULT_EV_COMP            0.0
#define DEFAULT_FLASH_MODE         0
#define DEFAULT_IMAGE_ISO          0
#define DEFAULT_IMAGE_RESOLUTION   "high"
#define DEFAULT_IMAGE_ASPECT_RATIO "16:9"
#define DEFAULT_VIDEO_RESOLUTION   "high"
#define DEFAULT_SOUND_ENABLED      true
#define DEFAULT_VIDEO_TORCH_ON     false

Settings::Settings(QObject *parent) :
  QObject(parent),
  m_settings(new QSettings(PATH, QSettings::IniFormat, this)) {

}

Settings::~Settings() {
  delete m_settings; m_settings = 0;
}

int Settings::mode() const {
  return m_settings->value("camera/mode", DEFAULT_MODE).toInt();
}

void Settings::setMode(int mode) {
  if (mode != Settings::mode()) {
    m_settings->setValue("camera/mode", mode);

    emit modeChanged();
  }
}

QString Settings::creatorName() const {
  return m_settings->value("camera/creatorName").toString();
}

void Settings::setCreatorName(const QString& name) {
  if (name != creatorName()) {
    m_settings->setValue("camera/creatorName", name);

    emit creatorNameChanged();
  }
}

int Settings::postCaptureTimeout() const {
  return m_settings->value("camera/postCaptureTimeout", DEFAULT_TIMEOUT).toInt();
}

void Settings::setPostCaptureTimeout(int timeout) {
  if (timeout != postCaptureTimeout()) {
    m_settings->setValue("camera/postCaptureTimeout", timeout);

    emit postCaptureTimeoutChanged();
  }
}

bool Settings::useGps() const {
  return m_settings->value("camera/useGps", DEFAULT_USE_GPS).toBool();
}

void Settings::setUseGps(bool enable) {
  if (enable != useGps()) {
    m_settings->setValue("camera/useGps", enable);

    emit useGpsChanged();
  }
}

bool Settings::useGeotags() const {
  return m_settings->value("camera/useGeotags", DEFAULT_USE_GEOTAGS).toBool();
}

void Settings::setUseGeotags(bool enable) {
  if (enable != useGeotags()) {
    m_settings->setValue("camera/useGeotags", enable);

    emit useGeotagsChanged();
  }
}

int Settings::imageSceneMode() const {
  return m_settings->value("image/sceneMode", DEFAULT_SCENE_MODE).toInt();
}

void Settings::setImageSceneMode(int mode) {
  if (mode != imageSceneMode()) {
    m_settings->setValue("image/sceneMode", mode);
  }

  emit imageSceneModeChanged();
}

int Settings::imageColorFilter() const {
  return m_settings->value("image/colorFilter", DEFAULT_COLOR_FILTER).toInt();
}

void Settings::setImageColorFilter(int filter) {
  if (filter != imageColorFilter()) {
    m_settings->setValue("image/colorFilter", filter);

    emit imageColorFilterChanged();
  }
}

int Settings::imageWhiteBalance() const {
  return m_settings->value("image/whiteBalance", DEFAULT_WHITE_BALANCE).toInt();
}

void Settings::setImageWhiteBalance(int wb) {
  if (wb != imageWhiteBalance()) {
    m_settings->setValue("image/whiteBalance", wb);

    emit imageWhiteBalanceChanged();
  }
}

qreal Settings::imageEvComp() const {
  return m_settings->value("image/evComp", DEFAULT_EV_COMP).toReal();
}

void Settings::setImageEvComp(qreal ev) {
  if (ev != imageEvComp()) {
    m_settings->setValue("image/evComp", ev);

    emit imageEvCompChanged();
  }
}

int Settings::videoSceneMode() const {
  return m_settings->value("video/sceneMode", DEFAULT_SCENE_MODE).toInt();
}

void Settings::setVideoSceneMode(int mode) {
  if (mode != videoSceneMode()) {
    m_settings->setValue("video/sceneMode", mode);
  }

  emit videoSceneModeChanged();
}

int Settings::videoColorFilter() const {
  return m_settings->value("video/colorFilter", DEFAULT_COLOR_FILTER).toInt();
}

void Settings::setVideoColorFilter(int filter) {
  if (filter != videoColorFilter()) {
    m_settings->setValue("video/colorFilter", filter);

    emit videoColorFilterChanged();
  }
}

int Settings::videoWhiteBalance() const {
  return m_settings->value("video/whiteBalance", DEFAULT_WHITE_BALANCE).toInt();
}

void Settings::setVideoWhiteBalance(int wb) {
  if (wb != videoWhiteBalance()) {
    m_settings->setValue("video/whiteBalance", wb);

    emit videoWhiteBalanceChanged();
  }
}

qreal Settings::videoEvComp() const {
  return m_settings->value("video/evComp", DEFAULT_EV_COMP).toReal();
}

void Settings::setVideoEvComp(qreal ev) {
  if (ev != videoEvComp()) {
    m_settings->setValue("video/evComp", ev);

    emit videoEvCompChanged();
  }
}

int Settings::imageFlashMode() const {
  return m_settings->value("image/flashMode", DEFAULT_FLASH_MODE).toInt();
}

void Settings::setImageFlashMode(int mode) {
  if (mode != imageFlashMode()) {
    m_settings->setValue("image/flashMode", mode);

    emit imageFlashModeChanged();
  }
}

int Settings::imageIso() const {
  return m_settings->value("image/iso", DEFAULT_IMAGE_ISO).toInt();
}

void Settings::setImageIso(int iso) {
  if (imageIso() != iso) {
    m_settings->setValue("image/iso", iso);
    emit imageIsoChanged();
  }
}

QString Settings::imageAspectRatio() const {
  return m_settings->value("image/aspectRatio", DEFAULT_IMAGE_ASPECT_RATIO).toString();
}

void Settings::setImageAspectRatio(const QString& aspectRatio) {
  if (aspectRatio != imageAspectRatio()) {
    m_settings->setValue("image/aspectRatio", aspectRatio);
    emit imageAspectRatioChanged();
  }
}

QString Settings::imageResolution() const {
  return m_settings->value("image/resolution", DEFAULT_IMAGE_RESOLUTION).toString();
}

void Settings::setImageResolution(const QString& resolution) {
  if (resolution != imageResolution()) {
    m_settings->setValue("image/resolution", resolution);
    emit imageResolutionChanged();
  }
}

QString Settings::videoAspectRatio() const {
  // This is not used for anything so we will return an empty string for now
  // which will make the backend return all resolutions.

  return QString();
}

void Settings::setVideoAspectRatio(const QString& aspectRatio) {
  Q_UNUSED(aspectRatio);

  // This is not used for anything so we will just ignore it.
}

QString Settings::videoResolution() const {
  return m_settings->value("video/resolution", DEFAULT_VIDEO_RESOLUTION).toString();
}

void Settings::setVideoResolution(const QString& resolution) {
  if (resolution != videoResolution()) {
    m_settings->setValue("video/resolution", resolution);
    emit videoResolutionChanged();
  }
}

bool Settings::isSoundEnabled() const {
  return m_settings->value("camera/soundEnabled", DEFAULT_SOUND_ENABLED).toBool();
}

void Settings::setSoundEnabled(bool enabled) {
  if (isSoundEnabled() != enabled) {
    m_settings->setValue("camera/soundEnabled", enabled);
    emit soundEnabledChanged();
  }
}

bool Settings::isVideoTorchOn() const {
  return m_settings->value("video/torchOn", DEFAULT_VIDEO_TORCH_ON).toBool();
}

void Settings::setVideoTorchOn(bool on) {
  if (isVideoTorchOn() != on) {
    m_settings->setValue("video/torchOn", on);
    emit videoTorchOnChanged();
  }
}
<commit_msg>Set default camera mode to image<commit_after>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "settings.h"
#include <QSettings>
#include <QDir>

#define PATH QString("%1%2.config%2/cameraplus.conf").arg(QDir::homePath()).arg(QDir::separator())

#define DEFAULT_MODE               1
#define DEFAULT_SCENE_MODE         6 // Auto
#define DEFAULT_TIMEOUT            0
#define DEFAULT_USE_GPS            true
#define DEFAULT_USE_GEOTAGS        true
#define DEFAULT_COLOR_FILTER       0
#define DEFAULT_WHITE_BALANCE      0
#define DEFAULT_EV_COMP            0.0
#define DEFAULT_FLASH_MODE         0
#define DEFAULT_IMAGE_ISO          0
#define DEFAULT_IMAGE_RESOLUTION   "high"
#define DEFAULT_IMAGE_ASPECT_RATIO "16:9"
#define DEFAULT_VIDEO_RESOLUTION   "high"
#define DEFAULT_SOUND_ENABLED      true
#define DEFAULT_VIDEO_TORCH_ON     false

Settings::Settings(QObject *parent) :
  QObject(parent),
  m_settings(new QSettings(PATH, QSettings::IniFormat, this)) {

}

Settings::~Settings() {
  delete m_settings; m_settings = 0;
}

int Settings::mode() const {
  return m_settings->value("camera/mode", DEFAULT_MODE).toInt();
}

void Settings::setMode(int mode) {
  if (mode != Settings::mode()) {
    m_settings->setValue("camera/mode", mode);

    emit modeChanged();
  }
}

QString Settings::creatorName() const {
  return m_settings->value("camera/creatorName").toString();
}

void Settings::setCreatorName(const QString& name) {
  if (name != creatorName()) {
    m_settings->setValue("camera/creatorName", name);

    emit creatorNameChanged();
  }
}

int Settings::postCaptureTimeout() const {
  return m_settings->value("camera/postCaptureTimeout", DEFAULT_TIMEOUT).toInt();
}

void Settings::setPostCaptureTimeout(int timeout) {
  if (timeout != postCaptureTimeout()) {
    m_settings->setValue("camera/postCaptureTimeout", timeout);

    emit postCaptureTimeoutChanged();
  }
}

bool Settings::useGps() const {
  return m_settings->value("camera/useGps", DEFAULT_USE_GPS).toBool();
}

void Settings::setUseGps(bool enable) {
  if (enable != useGps()) {
    m_settings->setValue("camera/useGps", enable);

    emit useGpsChanged();
  }
}

bool Settings::useGeotags() const {
  return m_settings->value("camera/useGeotags", DEFAULT_USE_GEOTAGS).toBool();
}

void Settings::setUseGeotags(bool enable) {
  if (enable != useGeotags()) {
    m_settings->setValue("camera/useGeotags", enable);

    emit useGeotagsChanged();
  }
}

int Settings::imageSceneMode() const {
  return m_settings->value("image/sceneMode", DEFAULT_SCENE_MODE).toInt();
}

void Settings::setImageSceneMode(int mode) {
  if (mode != imageSceneMode()) {
    m_settings->setValue("image/sceneMode", mode);
  }

  emit imageSceneModeChanged();
}

int Settings::imageColorFilter() const {
  return m_settings->value("image/colorFilter", DEFAULT_COLOR_FILTER).toInt();
}

void Settings::setImageColorFilter(int filter) {
  if (filter != imageColorFilter()) {
    m_settings->setValue("image/colorFilter", filter);

    emit imageColorFilterChanged();
  }
}

int Settings::imageWhiteBalance() const {
  return m_settings->value("image/whiteBalance", DEFAULT_WHITE_BALANCE).toInt();
}

void Settings::setImageWhiteBalance(int wb) {
  if (wb != imageWhiteBalance()) {
    m_settings->setValue("image/whiteBalance", wb);

    emit imageWhiteBalanceChanged();
  }
}

qreal Settings::imageEvComp() const {
  return m_settings->value("image/evComp", DEFAULT_EV_COMP).toReal();
}

void Settings::setImageEvComp(qreal ev) {
  if (ev != imageEvComp()) {
    m_settings->setValue("image/evComp", ev);

    emit imageEvCompChanged();
  }
}

int Settings::videoSceneMode() const {
  return m_settings->value("video/sceneMode", DEFAULT_SCENE_MODE).toInt();
}

void Settings::setVideoSceneMode(int mode) {
  if (mode != videoSceneMode()) {
    m_settings->setValue("video/sceneMode", mode);
  }

  emit videoSceneModeChanged();
}

int Settings::videoColorFilter() const {
  return m_settings->value("video/colorFilter", DEFAULT_COLOR_FILTER).toInt();
}

void Settings::setVideoColorFilter(int filter) {
  if (filter != videoColorFilter()) {
    m_settings->setValue("video/colorFilter", filter);

    emit videoColorFilterChanged();
  }
}

int Settings::videoWhiteBalance() const {
  return m_settings->value("video/whiteBalance", DEFAULT_WHITE_BALANCE).toInt();
}

void Settings::setVideoWhiteBalance(int wb) {
  if (wb != videoWhiteBalance()) {
    m_settings->setValue("video/whiteBalance", wb);

    emit videoWhiteBalanceChanged();
  }
}

qreal Settings::videoEvComp() const {
  return m_settings->value("video/evComp", DEFAULT_EV_COMP).toReal();
}

void Settings::setVideoEvComp(qreal ev) {
  if (ev != videoEvComp()) {
    m_settings->setValue("video/evComp", ev);

    emit videoEvCompChanged();
  }
}

int Settings::imageFlashMode() const {
  return m_settings->value("image/flashMode", DEFAULT_FLASH_MODE).toInt();
}

void Settings::setImageFlashMode(int mode) {
  if (mode != imageFlashMode()) {
    m_settings->setValue("image/flashMode", mode);

    emit imageFlashModeChanged();
  }
}

int Settings::imageIso() const {
  return m_settings->value("image/iso", DEFAULT_IMAGE_ISO).toInt();
}

void Settings::setImageIso(int iso) {
  if (imageIso() != iso) {
    m_settings->setValue("image/iso", iso);
    emit imageIsoChanged();
  }
}

QString Settings::imageAspectRatio() const {
  return m_settings->value("image/aspectRatio", DEFAULT_IMAGE_ASPECT_RATIO).toString();
}

void Settings::setImageAspectRatio(const QString& aspectRatio) {
  if (aspectRatio != imageAspectRatio()) {
    m_settings->setValue("image/aspectRatio", aspectRatio);
    emit imageAspectRatioChanged();
  }
}

QString Settings::imageResolution() const {
  return m_settings->value("image/resolution", DEFAULT_IMAGE_RESOLUTION).toString();
}

void Settings::setImageResolution(const QString& resolution) {
  if (resolution != imageResolution()) {
    m_settings->setValue("image/resolution", resolution);
    emit imageResolutionChanged();
  }
}

QString Settings::videoAspectRatio() const {
  // This is not used for anything so we will return an empty string for now
  // which will make the backend return all resolutions.

  return QString();
}

void Settings::setVideoAspectRatio(const QString& aspectRatio) {
  Q_UNUSED(aspectRatio);

  // This is not used for anything so we will just ignore it.
}

QString Settings::videoResolution() const {
  return m_settings->value("video/resolution", DEFAULT_VIDEO_RESOLUTION).toString();
}

void Settings::setVideoResolution(const QString& resolution) {
  if (resolution != videoResolution()) {
    m_settings->setValue("video/resolution", resolution);
    emit videoResolutionChanged();
  }
}

bool Settings::isSoundEnabled() const {
  return m_settings->value("camera/soundEnabled", DEFAULT_SOUND_ENABLED).toBool();
}

void Settings::setSoundEnabled(bool enabled) {
  if (isSoundEnabled() != enabled) {
    m_settings->setValue("camera/soundEnabled", enabled);
    emit soundEnabledChanged();
  }
}

bool Settings::isVideoTorchOn() const {
  return m_settings->value("video/torchOn", DEFAULT_VIDEO_TORCH_ON).toBool();
}

void Settings::setVideoTorchOn(bool on) {
  if (isVideoTorchOn() != on) {
    m_settings->setValue("video/torchOn", on);
    emit videoTorchOnChanged();
  }
}
<|endoftext|>


<commit_before>/*
 * Skaffari - a mail account administration web interface based on Cutelyst
 * Copyright (C) 2017 Matthias Fehring <kontakt@buschmann23.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "skaffari.h"

#include <Cutelyst/Application>
#include <Cutelyst/Plugins/StaticSimple/StaticSimple>
#include <Cutelyst/Plugins/View/Grantlee/grantleeview.h>
#include <Cutelyst/Plugins/Session/Session>
#include <Cutelyst/Plugins/Authentication/authentication.h>
#include <Cutelyst/Plugins/Authentication/credentialpassword.h>
#include <Cutelyst/Plugins/Authentication/authenticationrealm.h>
#include <Cutelyst/Plugins/Utils/Sql>
#include <Cutelyst/Plugins/StatusMessage>
#include <Cutelyst/Engine>
#include <grantlee5/grantlee/metatype.h>
#include <grantlee5/grantlee/engine.h>
#include <QSqlDatabase>
#include <QSqlError>
#include <QDir>
#include <QMetaType>

#include "objects/domain.h"
#include "objects/simpleadmin.h"
#include "objects/simpledomain.h"
#include "objects/adminaccount.h"
#include "objects/account.h"
#include "objects/folder.h"

#include "utils/language.h"

#include "../common/config.h"
#include "root.h"
#include "authstoresql.h"
#include "login.h"
#include "logout.h"
#include "domaineditor.h"
#include "accounteditor.h"
#include "skaffariengine.h"
#include "admineditor.h"
#include "myaccount.h"

Q_LOGGING_CATEGORY(SK_CORE, "skaffari.core")

using namespace Cutelyst;

Skaffari::Skaffari(QObject *parent) : Application(parent)
{
}

Skaffari::~Skaffari()
{
}

bool Skaffari::init()
{
    qRegisterMetaType<Folder>();
    qRegisterMetaType<Domain>();
    qRegisterMetaType<SimpleAdmin>();
    qRegisterMetaType<SimpleDomain>();
    qRegisterMetaType<AdminAccount>();
    qRegisterMetaType<Language>();
    qRegisterMetaType<Account>();

    Grantlee::registerMetaType<Folder>();
    Grantlee::registerMetaType<Domain>();
    Grantlee::registerMetaType<SimpleAdmin>();
    Grantlee::registerMetaType<SimpleDomain>();
    Grantlee::registerMetaType<AdminAccount>();
    Grantlee::registerMetaType<Language>();
    Grantlee::registerMetaType<Account>();

    QString tmplBasePath = QStringLiteral(SKAFFARI_TMPLDIR);
    tmplBasePath.append(QLatin1Char('/')).append(config(QStringLiteral("template"), QStringLiteral("default")).toString());
    QString sitePath = tmplBasePath;
    sitePath.append(QLatin1Char('/')).append(QStringLiteral("site"));

    auto view = new GrantleeView(this);
    view->setTemplateExtension(QStringLiteral(".html"));
    view->setWrapper(QStringLiteral("wrapper.html"));
	view->setCache(false);
    view->setIncludePaths({sitePath});
    view->engine()->addDefaultLibrary(QStringLiteral("grantlee_i18ntags"));

	new Root(this);
	new Login(this);
	new Logout(this);
	new DomainEditor(this);
	new AccountEditor(this);
    new AdminEditor(this);
    new MyAccount(this);

    auto staticSimple = new StaticSimple(this);
    QString staticPath = tmplBasePath;
    staticPath.append(QLatin1Char('/')).append(QStringLiteral("static"));
    staticSimple->setIncludePaths({staticPath});

	new Session(this);

    new StatusMessage(this);

    auto auth = new Authentication(this);
    auto credential = new CredentialPassword(auth);
    credential->setPasswordType(CredentialPassword::Hashed);
    auto store = new AuthStoreSql(this);
    auto realm = new AuthenticationRealm(store, credential, auth);
    store->setParent(realm);
    auth->addRealm(store, credential);

    defaultHeaders().setHeader(QStringLiteral("X-Frame-Options"), QStringLiteral("DENY"));
    defaultHeaders().setHeader(QStringLiteral("X-Content-Type-Options"), QStringLiteral("nosniff"));
    defaultHeaders().setHeader(QStringLiteral("X-XSS-Protection"), QStringLiteral("1; mode=block"));
    defaultHeaders().setHeader(QStringLiteral("Content-Security-Policy"), QStringLiteral("default-src 'none'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; connect-src 'self';"));

    return true;
}

bool Skaffari::postFork()
{
    const QVariantMap dbconfig = this->engine()->config(QStringLiteral("Database"));
    const QString dbtype = dbconfig.value(QStringLiteral("type")).toString();
    const QString dbname = dbconfig.value(QStringLiteral("name")).toString();
    const QString dbuser = dbconfig.value(QStringLiteral("user")).toString();
    const QString dbpass = dbconfig.value(QStringLiteral("password")).toString();
    const QString dbhost = dbconfig.value(QStringLiteral("host")).toString();
    const int dbport = dbconfig.value(QStringLiteral("port")).toInt();

    QSqlDatabase db;
    if (dbtype == QLatin1String("QMYSQL")) {
        if (dbname.isEmpty() || dbuser.isEmpty() || dbpass.isEmpty()) {
            qCCritical(SK_CORE) << "Database name, database user or database password can not be empty.";
            return false;
        }

        db = QSqlDatabase::addDatabase(dbtype, Sql::databaseNameThread());
        db.setDatabaseName(dbname);
        db.setUserName(dbuser);
        db.setPassword(dbpass);

        if (dbhost[0] == QLatin1Char('/')) {
            db.setConnectOptions(QStringLiteral("UNIX_SOCKET=%1").arg(dbhost));
        } else {
            db.setHostName(dbhost);
            db.setPort(dbport);
        }
    } else {
        qCCritical(SK_CORE) << "No supported databse type in configuration.";
        return false;
    }

    if (!db.open()) {
        qCCritical(SK_CORE) << "Failed to establish database connection:" << db.lastError().text();
        return false;
    }

    auto engine = new SkaffariEngine(this);

    if (!engine->init(this->engine()->config(QStringLiteral("Admins")),
                      this->engine()->config(QStringLiteral("Defaults")),
                      this->engine()->config(QStringLiteral("Accounts")),
                      this->engine()->config(QStringLiteral("IMAP")))) {
		return false;
	}

    const QVector<Controller*> constControllers = controllers();
    for (Controller *c : constControllers) {
        auto sengine = dynamic_cast<SEngine*>(c);
        if (sengine) {
            sengine->engine = engine;
        }
    }

    return true;
}

#include "moc_skaffari.cpp"
<commit_msg>Set application name to Skaffari, use QStringBuilder<commit_after>/*
 * Skaffari - a mail account administration web interface based on Cutelyst
 * Copyright (C) 2017 Matthias Fehring <kontakt@buschmann23.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "skaffari.h"

#include <Cutelyst/Application>
#include <Cutelyst/Plugins/StaticSimple/StaticSimple>
#include <Cutelyst/Plugins/View/Grantlee/grantleeview.h>
#include <Cutelyst/Plugins/Session/Session>
#include <Cutelyst/Plugins/Authentication/authentication.h>
#include <Cutelyst/Plugins/Authentication/credentialpassword.h>
#include <Cutelyst/Plugins/Authentication/authenticationrealm.h>
#include <Cutelyst/Plugins/Utils/Sql>
#include <Cutelyst/Plugins/StatusMessage>
#include <Cutelyst/Engine>
#include <grantlee5/grantlee/metatype.h>
#include <grantlee5/grantlee/engine.h>
#include <QSqlDatabase>
#include <QSqlError>
#include <QDir>
#include <QMetaType>
#include <QCoreApplication>

#include "objects/domain.h"
#include "objects/simpleadmin.h"
#include "objects/simpledomain.h"
#include "objects/adminaccount.h"
#include "objects/account.h"
#include "objects/folder.h"

#include "utils/language.h"

#include "../common/config.h"
#include "root.h"
#include "authstoresql.h"
#include "login.h"
#include "logout.h"
#include "domaineditor.h"
#include "accounteditor.h"
#include "skaffariengine.h"
#include "admineditor.h"
#include "myaccount.h"

Q_LOGGING_CATEGORY(SK_CORE, "skaffari.core")

using namespace Cutelyst;

Skaffari::Skaffari(QObject *parent) : Application(parent)
{
}

Skaffari::~Skaffari()
{
}

bool Skaffari::init()
{
    QCoreApplication::setApplicationName(QStringLiteral("Skaffari"));

    qRegisterMetaType<Folder>();
    qRegisterMetaType<Domain>();
    qRegisterMetaType<SimpleAdmin>();
    qRegisterMetaType<SimpleDomain>();
    qRegisterMetaType<AdminAccount>();
    qRegisterMetaType<Language>();
    qRegisterMetaType<Account>();

    Grantlee::registerMetaType<Folder>();
    Grantlee::registerMetaType<Domain>();
    Grantlee::registerMetaType<SimpleAdmin>();
    Grantlee::registerMetaType<SimpleDomain>();
    Grantlee::registerMetaType<AdminAccount>();
    Grantlee::registerMetaType<Language>();
    Grantlee::registerMetaType<Account>();

    QString tmplBasePath = QStringLiteral(SKAFFARI_TMPLDIR) + QLatin1Char('/') + config(QStringLiteral("template"), QStringLiteral("default")).toString();
    QString sitePath = tmplBasePath + QLatin1String("/site");

    auto view = new GrantleeView(this);
    view->setTemplateExtension(QStringLiteral(".html"));
    view->setWrapper(QStringLiteral("wrapper.html"));
	view->setCache(false);
    view->setIncludePaths({sitePath});
    view->engine()->addDefaultLibrary(QStringLiteral("grantlee_i18ntags"));

	new Root(this);
	new Login(this);
	new Logout(this);
	new DomainEditor(this);
	new AccountEditor(this);
    new AdminEditor(this);
    new MyAccount(this);

    auto staticSimple = new StaticSimple(this);
    QString staticPath = tmplBasePath + QLatin1String("/static");
    staticSimple->setIncludePaths({staticPath});

	new Session(this);

    new StatusMessage(this);

    auto auth = new Authentication(this);
    auto credential = new CredentialPassword(auth);
    credential->setPasswordType(CredentialPassword::Hashed);
    auto store = new AuthStoreSql(this);
    auto realm = new AuthenticationRealm(store, credential, auth);
    store->setParent(realm);
    auth->addRealm(store, credential);

    defaultHeaders().setHeader(QStringLiteral("X-Frame-Options"), QStringLiteral("DENY"));
    defaultHeaders().setHeader(QStringLiteral("X-Content-Type-Options"), QStringLiteral("nosniff"));
    defaultHeaders().setHeader(QStringLiteral("X-XSS-Protection"), QStringLiteral("1; mode=block"));
    defaultHeaders().setHeader(QStringLiteral("Content-Security-Policy"), QStringLiteral("default-src 'none'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self' data:; connect-src 'self';"));

    return true;
}

bool Skaffari::postFork()
{
    const QVariantMap dbconfig = this->engine()->config(QStringLiteral("Database"));
    const QString dbtype = dbconfig.value(QStringLiteral("type")).toString();
    const QString dbname = dbconfig.value(QStringLiteral("name")).toString();
    const QString dbuser = dbconfig.value(QStringLiteral("user")).toString();
    const QString dbpass = dbconfig.value(QStringLiteral("password")).toString();
    const QString dbhost = dbconfig.value(QStringLiteral("host")).toString();
    const int dbport = dbconfig.value(QStringLiteral("port")).toInt();

    QSqlDatabase db;
    if (dbtype == QLatin1String("QMYSQL")) {
        if (dbname.isEmpty() || dbuser.isEmpty() || dbpass.isEmpty()) {
            qCCritical(SK_CORE) << "Database name, database user or database password can not be empty.";
            return false;
        }

        db = QSqlDatabase::addDatabase(dbtype, Sql::databaseNameThread());
        db.setDatabaseName(dbname);
        db.setUserName(dbuser);
        db.setPassword(dbpass);

        if (dbhost[0] == QLatin1Char('/')) {
            db.setConnectOptions(QStringLiteral("UNIX_SOCKET=%1").arg(dbhost));
        } else {
            db.setHostName(dbhost);
            db.setPort(dbport);
        }
    } else {
        qCCritical(SK_CORE) << "No supported databse type in configuration.";
        return false;
    }

    if (!db.open()) {
        qCCritical(SK_CORE) << "Failed to establish database connection:" << db.lastError().text();
        return false;
    }

    auto engine = new SkaffariEngine(this);

    if (!engine->init(this->engine()->config(QStringLiteral("Admins")),
                      this->engine()->config(QStringLiteral("Defaults")),
                      this->engine()->config(QStringLiteral("Accounts")),
                      this->engine()->config(QStringLiteral("IMAP")))) {
		return false;
	}

    const QVector<Controller*> constControllers = controllers();
    for (Controller *c : constControllers) {
        auto sengine = dynamic_cast<SEngine*>(c);
        if (sengine) {
            sengine->engine = engine;
        }
    }

    return true;
}

#include "moc_skaffari.cpp"
<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkFixedArrayTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#include <iostream>

#include "itkFixedArray.h"

// Explicit instantiation to make sure all methods are compiled.
template class itk::FixedArray<float, 3>;

void Set_c_Array(int x[3])
{
  x[0] = 1;
  x[1] = 2;
  x[2] = 3;
}

void Print_Array(itk::FixedArray<int, 3> x, std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << '}' << std::endl;
}

void Print_c_ArrayConst(const int x[3], std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << '}' << std::endl;
}

void Print_Array5(itk::FixedArray<int, 5> x, std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << ','
     << x[3] << ',' << x[4] << '}' << std::endl;
}

int itkFixedArrayTest(int, char* [] )
{
  // Test out many combinations of using c-style arrays and FixedArray

  int c_Array1[3] = {0,0,0};

  Set_c_Array(c_Array1);
  Print_Array(c_Array1, std::cout);
  Print_c_ArrayConst(c_Array1, std::cout);

  int c_Array2[3] = {0,0,0};
  Print_Array(c_Array2, std::cout);

  int array3Init[3] = {4,4,4};
  itk::FixedArray<int, 3> array3 = array3Init;
  Print_Array(array3, std::cout);
  Print_c_ArrayConst(array3.GetDataPointer(), std::cout);

  Set_c_Array(array3.GetDataPointer());
  Print_Array(array3, std::cout);

  itk::FixedArray<int, 3> array4;
  Print_Array(array4, std::cout);

  // Test operator!= and operator==
  if ( array4 != array4 ) return 1; //should be equal
  if ( !(array4 == array4) ) return 1; //should be equal

  return 0;
}
<commit_msg>ENH: GetElement()/SetElement() methods exercised.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkFixedArrayTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#include <iostream>

#include "itkFixedArray.h"

// Explicit instantiation to make sure all methods are compiled.
template class itk::FixedArray<float, 3>;

void Set_c_Array(int x[3])
{
  x[0] = 1;
  x[1] = 2;
  x[2] = 3;
}

void Print_Array(itk::FixedArray<int, 3> x, std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << '}' << std::endl;
}

void Print_c_ArrayConst(const int x[3], std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << '}' << std::endl;
}

void Print_Array5(itk::FixedArray<int, 5> x, std::ostream& os)
{
  os << '{' << x[0] << ',' << x[1] << ',' << x[2] << ','
     << x[3] << ',' << x[4] << '}' << std::endl;
}

int itkFixedArrayTest(int, char* [] )
{
  // Test out many combinations of using c-style arrays and FixedArray

  int c_Array1[3] = {0,0,0};

  Set_c_Array(c_Array1);
  Print_Array(c_Array1, std::cout);
  Print_c_ArrayConst(c_Array1, std::cout);

  int c_Array2[3] = {0,0,0};
  Print_Array(c_Array2, std::cout);

  int array3Init[3] = {4,4,4};
  itk::FixedArray<int, 3> array3 = array3Init;
  Print_Array(array3, std::cout);
  Print_c_ArrayConst(array3.GetDataPointer(), std::cout);

  Set_c_Array(array3.GetDataPointer());
  Print_Array(array3, std::cout);

  itk::FixedArray<int, 3> array4;
  Print_Array(array4, std::cout);

  // Test operator!= and operator==
  if ( array4 != array4 ) return 1; //should be equal
  if ( !(array4 == array4) ) return 1; //should be equal

  // Test Get/Set element
  const unsigned int n = 20;
  itk::FixedArray< int, n > array20;
  for(unsigned int i=0; i<n; i++)
    {
    array20.SetElement(i,i);
    }

  for(unsigned int k=0; k<n; k++)
    {
    if( array20.GetElement(k) != k )
      {
      std::cerr << "Set/Get element test failed" << std::endl;
      return EXIT_FAILURE;
      }
    }

  return 0;
}
<|endoftext|>


<commit_before>/*
 *          Copyright Andrey Semashev 2007 - 2014.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
/*!
 * \file   sources/features.hpp
 * \author Andrey Semashev
 * \date   17.07.2009
 *
 * The header contains definition of a features list class template.
 */

#ifndef BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_

#include <boost/mpl/lambda.hpp>
#include <boost/log/detail/config.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)

#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_binary_params.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>

//! The macro defines the maximum number of features that can be specified for a logger
#ifndef BOOST_LOG_FEATURES_LIMIT
#define BOOST_LOG_FEATURES_LIMIT 10
#endif // BOOST_LOG_FEATURES_LIMIT

#endif

#include <boost/log/detail/header.hpp>

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

namespace sources {

#if defined(BOOST_LOG_DOXYGEN_PASS) || !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)

/*!
 * \brief A type sequence of logger features
 *
 * This class template can be used to specify logger features in a \c basic_composite_logger instantiation.
 */
template< typename... FeaturesT >
struct features
{
};

namespace aux {

//! The metafunction produces the inherited features hierarchy with \c RootT as the ultimate base type
template< typename RootT, typename FeaturesT >
struct inherit_features;

template< typename RootT, typename FeatureT0, typename... FeaturesT >
struct inherit_features< RootT, features< FeatureT0, FeaturesT... > >
{
    typedef typename mpl::lambda<
        FeatureT0
    >::type::BOOST_NESTED_TEMPLATE apply<
        typename inherit_features<
            RootT,
            features< FeaturesT... >
        >::type
    >::type type;
};

template< typename RootT, typename FeatureT0 >
struct inherit_features< RootT, features< FeatureT0 > >
{
    typedef typename mpl::lambda<
        FeatureT0
    >::type::BOOST_NESTED_TEMPLATE apply<
        RootT
    >::type type;
};

template< typename RootT >
struct inherit_features< RootT, features< > >
{
    typedef RootT type;
};

} // namespace aux

#else

//! A type sequence of logger features
template< BOOST_PP_ENUM_BINARY_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT, = void BOOST_PP_INTERCEPT) >
struct features
{
};

namespace aux {

template< typename RootT, typename FeaturesT >
struct inherit_features;

template< typename RootT, BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT) >
struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) > >
{
    typedef typename mpl::lambda<
        FeatureT0
    >::type::BOOST_NESTED_TEMPLATE apply<
        typename inherit_features<
            RootT,
            features< BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) >
        >::type
    >::type type;
};

template< typename RootT, typename FeatureT0 >
struct inherit_features< RootT, features< FeatureT0, BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > >
{
    typedef typename mpl::lambda<
        FeatureT0
    >::type::BOOST_NESTED_TEMPLATE apply<
        RootT
    >::type type;
};

template< typename RootT >
struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > >
{
    typedef RootT type;
};

} // namespace aux

#endif

} // namespace sources

BOOST_LOG_CLOSE_NAMESPACE // namespace log

} // namespace boost

#include <boost/log/detail/footer.hpp>

#endif // BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
<commit_msg>Fixed missing #include.<commit_after>/*
 *          Copyright Andrey Semashev 2007 - 2014.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
/*!
 * \file   sources/features.hpp
 * \author Andrey Semashev
 * \date   17.07.2009
 *
 * The header contains definition of a features list class template.
 */

#ifndef BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_

#include <boost/mpl/lambda.hpp>
#include <boost/log/detail/config.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif

#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)

#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>

//! The macro defines the maximum number of features that can be specified for a logger
#ifndef BOOST_LOG_FEATURES_LIMIT
#define BOOST_LOG_FEATURES_LIMIT 10
#endif // BOOST_LOG_FEATURES_LIMIT

#endif

#include <boost/log/detail/header.hpp>

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

namespace sources {

#if defined(BOOST_LOG_DOXYGEN_PASS) || !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)

/*!
 * \brief A type sequence of logger features
 *
 * This class template can be used to specify logger features in a \c basic_composite_logger instantiation.
 */
template< typename... FeaturesT >
struct features
{
};

namespace aux {

//! The metafunction produces the inherited features hierarchy with \c RootT as the ultimate base type
template< typename RootT, typename FeaturesT >
struct inherit_features;

template< typename RootT, typename FeatureT0, typename... FeaturesT >
struct inherit_features< RootT, features< FeatureT0, FeaturesT... > >
{
    typedef typename mpl::lambda<
        FeatureT0
    >::type::BOOST_NESTED_TEMPLATE apply<
        typename inherit_features<
            RootT,
            features< FeaturesT... >
        >::type
    >::type type;
};

template< typename RootT, typename FeatureT0 >
struct inherit_features< RootT, features< FeatureT0 > >
{
    typedef typename mpl::lambda<
        FeatureT0
    >::type::BOOST_NESTED_TEMPLATE apply<
        RootT
    >::type type;
};

template< typename RootT >
struct inherit_features< RootT, features< > >
{
    typedef RootT type;
};

} // namespace aux

#else

//! A type sequence of logger features
template< BOOST_PP_ENUM_BINARY_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT, = void BOOST_PP_INTERCEPT) >
struct features
{
};

namespace aux {

template< typename RootT, typename FeaturesT >
struct inherit_features;

template< typename RootT, BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT) >
struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) > >
{
    typedef typename mpl::lambda<
        FeatureT0
    >::type::BOOST_NESTED_TEMPLATE apply<
        typename inherit_features<
            RootT,
            features< BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) >
        >::type
    >::type type;
};

template< typename RootT, typename FeatureT0 >
struct inherit_features< RootT, features< FeatureT0, BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > >
{
    typedef typename mpl::lambda<
        FeatureT0
    >::type::BOOST_NESTED_TEMPLATE apply<
        RootT
    >::type type;
};

template< typename RootT >
struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > >
{
    typedef RootT type;
};

} // namespace aux

#endif

} // namespace sources

BOOST_LOG_CLOSE_NAMESPACE // namespace log

} // namespace boost

#include <boost/log/detail/footer.hpp>

#endif // BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
<|endoftext|>


<commit_before>//  (C) Copyright Gennadiy Rozental 2001-2002.
//  (C) Copyright Ullrich Koethe 2001.
//  Permission to copy, use, modify, sell and distribute this software
//  is granted provided this copyright notice appears in all copies.
//  This software is provided "as is" without express or implied warranty,
//  and with no claim as to its suitability for any purpose.

//  See http://www.boost.org for most recent version including documentation.
//
//  File        : $RCSfile$
//
//  Version     : $Id$
//
//  Description : defines all classes in test_case hierarchy and object generators
//  for them.
// ***************************************************************************

#ifndef BOOST_UNIT_TEST_SUITE_HPP
#define BOOST_UNIT_TEST_SUITE_HPP

// Boost.Test
#include <boost/test/detail/unit_test_monitor.hpp>
#include <boost/test/detail/unit_test_config.hpp>
#include <boost/test/detail/class_properties.hpp>

// BOOST
#include <boost/shared_ptr.hpp>

// STL
#include <string>  // for std::string

#define BOOST_TEST_CASE( function ) \
boost::unit_test_framework::create_test_case((function), #function )
#define BOOST_CLASS_TEST_CASE( function, tc_instance ) \
boost::unit_test_framework::create_test_case((function), #function, tc_instance )
#define BOOST_PARAM_TEST_CASE( function, begin, end ) \
boost::unit_test_framework::create_test_case((function), #function, (begin), (end) )
#define BOOST_PARAM_CLASS_TEST_CASE( function, tc_instance, begin, end ) \
boost::unit_test_framework::create_test_case((function), #function, tc_instance, (begin), (end) )
#define BOOST_TEST_SUITE( testsuite_name ) \
( new boost::unit_test_framework::test_suite( testsuite_name ) )

namespace boost {

namespace unit_test_framework {

// ************************************************************************** //
// **************                   test_case                  ************** //
// ************************************************************************** //

class test_case {
public:
    typedef detail::unit_test_monitor::error_level error_level_type;

    // Destructor
    virtual             ~test_case()    {}

    // number of tests in this test case
    virtual unit_test_counter size() const;

    // execute this method to run this test case; for now it is not supposed to be overwritten;
    void                run();

    // public properties
    BOOST_READONLY_PROPERTY( int, 2, (test_case,test_suite) )
                        p_timeout;                  // timeout for the excecution monitor
    BOOST_READONLY_PROPERTY( unit_test_counter, 2, (test_case,test_suite) )
                        p_expected_failures;        // number of aseertions that are expected to fail in this test case

protected:
    // protected properties
    BOOST_READONLY_PROPERTY( std::string, 1, (test_case) )
                        p_name;                     // name_ for this test case
    BOOST_READONLY_PROPERTY( bool, 2, (test_case,test_suite) )
                        p_compound_stage;           // used to properly manage progress report
    BOOST_READWRITE_PROPERTY( unit_test_counter )
                        p_stages_amount;            // number of stages this test consist of; stage could another test case
                                                    // like with test_suite, another parameterized test for parameterized_test_case
                                                    // or 1 stage that reflect single test_case behaviour

    // access methods
    void                curr_stage_is_compound();

    // Constructor
    explicit            test_case( char const*          name_           = "Unnamed",
                                   unit_test_counter    stages_number_  = 0,
                                   bool                 monitor_run_    = true );

    // test case implementation hooks to be called with unit_test_monitor or alone
    virtual void        do_init()       {}
    virtual void        do_run()        {}
    virtual void        do_destroy()    {}

private:
    // Data members
    bool                m_monitor_run;              // true - unit_test_monitor will be user to monitor running
                                                    // of implementation function
    static bool         s_abort_testing;            // used to flag critical error and try gracefully stop testing
};

//____________________________________________________________________________//

inline
test_case::test_case( char const* name_, unit_test_counter stages_number_, bool monitor_run_ )
: p_timeout( 0 ), p_expected_failures( 0 ),
  p_name( name_ ), p_compound_stage( false ), p_stages_amount( stages_number_ ),
  m_monitor_run( monitor_run_ )
{
}

//____________________________________________________________________________//

inline unit_test_counter
test_case::size() const
{
    return p_stages_amount;
}

//____________________________________________________________________________//

// ************************************************************************** //
// **************              function_test_case              ************** //
// ************************************************************************** //

class function_test_case : public test_case {
public:
    typedef void  (*function_type)();

    // Constructor
    function_test_case( function_type f_, char const* name_ )
    : test_case( name_, 1 ), m_function( f_ ) {}

protected:
    // test case implementation
    void                do_run()        { m_function(); }

private:
    // Data members
    function_type       m_function;
};

// ************************************************************************** //
// **************                class_test_case               ************** //
// ************************************************************************** //

template<class UserTestCase>
class class_test_case : public test_case {
public:
    typedef void  (UserTestCase::*function_type)();

    // Constructor
    class_test_case( function_type f_, char const* name_, boost::shared_ptr<UserTestCase>& user_test_case_ )
    : test_case( name_, 1 ), m_user_test_case( user_test_case_ ), m_function( f_ ) {}

private:
    // test case implementation
    void                do_run()        { ((*m_user_test_case).*m_function)(); }
    void                do_destroy()    { m_user_test_case.reset(); }

    // Data members
    boost::shared_ptr<UserTestCase> m_user_test_case;
    function_type       m_function;
};

// ************************************************************************** //
// **************        parametrized_function_test_case       ************** //
// ************************************************************************** //

template <typename ParamIterator, typename ParameterType>
class parametrized_function_test_case : public test_case {
public:
    typedef void  (*function_type)( ParameterType );

    // Constructor
    parametrized_function_test_case( function_type f_, char const* name_,
                                     ParamIterator const& par_begin_, ParamIterator const& par_end_ )
    : test_case( name_ ), m_first_parameter( par_begin_ ), m_last_parameter( par_end_ ), m_function( f_ )
    {
       // the typecasts are here to keep Borland C++ Builder 5 happy, for other compilers they have no effect:
       p_stages_amount.set( detail::distance( (ParamIterator)par_begin_, (ParamIterator)par_end_ ) );
    }

    // test case implementation
    void                do_init()       { m_curr_parameter = m_first_parameter; }
    void                do_run()        { m_function( *m_curr_parameter ); ++m_curr_parameter; }

private:
    // Data members
    ParamIterator       m_first_parameter;
    ParamIterator       m_last_parameter;
    ParamIterator       m_curr_parameter;

    function_type       m_function;
};

// ************************************************************************** //
// **************         parametrized_class_test_case         ************** //
// ************************************************************************** //

template <class UserTestCase, class ParamIterator, typename ParameterType>
class parametrized_class_test_case : public test_case {
public:
    typedef void  (UserTestCase::*function_type)( ParameterType );

    // Constructor
    parametrized_class_test_case( function_type f_, char const* name_, boost::shared_ptr<UserTestCase>& user_test_case_,
                                  ParamIterator const& par_begin_, ParamIterator const& par_end_ )
    : test_case( name_ ), m_first_parameter( par_begin_ ), m_last_parameter( par_end_ ),
      m_user_test_case( user_test_case_ ), m_function( f_ )
    {
       // the typecasts are here to keep Borland C++ Builder 5 happy, for other compilers they have no effect:
       p_stages_amount.set( detail::distance( (ParamIterator)par_begin_, (ParamIterator)par_end_ ) );
    }

    // test case implementation
    void                do_init()       { m_curr_parameter = m_first_parameter; }
    void                do_run()        { ((*m_user_test_case).*m_function)( *m_curr_parameter ); ++m_curr_parameter; }
    void                do_destroy()    { m_user_test_case.reset(); }

private:
    // Data members
    ParamIterator       m_first_parameter;
    ParamIterator       m_last_parameter;
    ParamIterator       m_curr_parameter;

    boost::shared_ptr<UserTestCase> m_user_test_case;
    function_type       m_function;
};

// ************************************************************************** //
// **************                  test_suite                  ************** //
// ************************************************************************** //

class test_suite : public test_case {
public:
    // Constructor
    explicit test_suite( char const* name_ = "Master" );

    // Destructor
    virtual             ~test_suite();

    // test case list management
    void                add( test_case* tc_, unit_test_counter expected_failures_ = 0, int timeout_ = 0 );

    // access methods
    unit_test_counter   size() const;

    // test case implementation
    void                do_init();
    void                do_run();

private:
    // Data members
    struct Impl;
    boost::shared_ptr<Impl> m_pimpl;
};

// ************************************************************************** //
// **************               object generators              ************** //
// ************************************************************************** //

namespace detail {

inline char const*
normalize_test_case_name( std::string& name_ )
{
    if( name_[0] == '&' )
        name_.erase( 0, 1 );

    return name_.data();
}

} // namespace detail

inline test_case*
create_test_case( void (*fct_)(), std::string name_ )
{
    return new function_test_case( fct_, detail::normalize_test_case_name( name_ ) );
}

template<class UserTestCase>
inline test_case*
create_test_case( void (UserTestCase::*fct_)(), std::string name_, boost::shared_ptr<UserTestCase>& user_test_case_ )
{
    return new class_test_case<UserTestCase>( fct_, detail::normalize_test_case_name( name_ ), user_test_case_ );
}

template<typename ParamIterator, typename ParamType>
inline test_case*
create_test_case( void (*fct_)( ParamType ), std::string name_, ParamIterator const& par_begin_, ParamIterator const& par_end_ )
{
    return new parametrized_function_test_case<ParamIterator,ParamType>(
        fct_, detail::normalize_test_case_name( name_ ), par_begin_, par_end_ );
}

template<class UserTestCase, typename ParamIterator, typename ParamType>
inline test_case*
create_test_case( void (UserTestCase::*fct_)( ParamType ), std::string name_, boost::shared_ptr<UserTestCase>& user_test_case_,
                  ParamIterator const& par_begin_, ParamIterator const& par_end_ )
{
    return new parametrized_class_test_case<UserTestCase,ParamIterator,ParamType>(
        fct_, detail::normalize_test_case_name( name_ ), user_test_case_, par_begin_, par_end_ );
}

} // unit_test_framework

} // namespace boost

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.11  2002/11/02 19:31:04  rogeeff
//  merged into the main trank
//

// ***************************************************************************

#endif // BOOST_UNIT_TEST_SUITE_HPP

<commit_msg>notion of number of stages is separated from number of test cases, so that parameterized test case in reported as one test case fixed bug in both parameterized function/class test cases with not iterating parameter iterator if exception occured switched to use c_string_literal<commit_after>//  (C) Copyright Gennadiy Rozental 2001-2002.
//  (C) Copyright Ullrich Koethe 2001.
//  Permission to copy, use, modify, sell and distribute this software
//  is granted provided this copyright notice appears in all copies.
//  This software is provided "as is" without express or implied warranty,
//  and with no claim as to its suitability for any purpose.

//  See http://www.boost.org for most recent version including documentation.
//
//  File        : $RCSfile$
//
//  Version     : $Id$
//
//  Description : defines all classes in test_case hierarchy and object generators
//  for them.
// ***************************************************************************

#ifndef BOOST_UNIT_TEST_SUITE_HPP
#define BOOST_UNIT_TEST_SUITE_HPP

// Boost.Test
#include <boost/test/detail/unit_test_monitor.hpp>
#include <boost/test/detail/unit_test_config.hpp>
#include <boost/test/detail/class_properties.hpp>

// BOOST
#include <boost/shared_ptr.hpp>

// STL
#include <string>  // for std::string

#define BOOST_TEST_CASE( function ) \
boost::unit_test_framework::create_test_case((function), #function )
#define BOOST_CLASS_TEST_CASE( function, tc_instance ) \
boost::unit_test_framework::create_test_case((function), #function, tc_instance )
#define BOOST_PARAM_TEST_CASE( function, begin, end ) \
boost::unit_test_framework::create_test_case((function), #function, (begin), (end) )
#define BOOST_PARAM_CLASS_TEST_CASE( function, tc_instance, begin, end ) \
boost::unit_test_framework::create_test_case((function), #function, tc_instance, (begin), (end) )
#define BOOST_TEST_SUITE( testsuite_name ) \
( new boost::unit_test_framework::test_suite( testsuite_name ) )

namespace boost {

namespace unit_test_framework {

// ************************************************************************** //
// **************                   test_case                  ************** //
// ************************************************************************** //

class test_case {
public:
    typedef detail::unit_test_monitor::error_level error_level_type;

    // Destructor
    virtual             ~test_case()    {}

    // number of tests in this test case
    virtual unit_test_counter size() const;
    virtual c_string_literal  type() const;         // case or suite

    // execute this method to run this test case
    void                run();

    // public properties
    BOOST_READONLY_PROPERTY( int, 2, (test_case,test_suite) )
                        p_timeout;                  // timeout for the excecution monitor
    BOOST_READONLY_PROPERTY( unit_test_counter, 1, (test_suite) )
                        p_expected_failures;        // number of aseertions that are expected to fail in this test case

protected:
    // protected properties
    BOOST_READONLY_PROPERTY( std::string, 0, () )
                        p_name;                     // name for this test case
    BOOST_READONLY_PROPERTY( bool, 2, (test_case,test_suite) )
                        p_compound_stage;           // used to properly manage progress report
    BOOST_READWRITE_PROPERTY( unit_test_counter )
                        p_stages_amount;            // number of stages this test consist of; stage could be another test case
                                                    // like with test_suite, another parameterized test for parameterized_test_case
                                                    // or 1 stage that reflect single test_case behaviour

    // access methods
    void                curr_stage_is_compound();

    // Constructor
    explicit            test_case( c_string_literal     name_           = "Unnamed",
                                   unit_test_counter    stages_number_  = 0,
                                   bool                 monitor_run_    = true );

    // test case implementation hooks to be called with unit_test_monitor or alone
    virtual void        do_init()       {}
    virtual void        do_run()        {}
    virtual void        do_destroy()    {}

private:
    // Data members
    bool                m_monitor_run;              // true - unit_test_monitor will be user to monitor running
                                                    // of implementation function
    static bool         s_abort_testing;            // used to flag critical error and try gracefully stop testing
};

//____________________________________________________________________________//

// ************************************************************************** //
// **************              function_test_case              ************** //
// ************************************************************************** //

class function_test_case : public test_case {
public:
    typedef void  (*function_type)();

    // Constructor
    function_test_case( function_type f_, c_string_literal name_ )
    : test_case( name_, 1 ), m_function( f_ ) {}

protected:
    // test case implementation
    void                do_run()        { m_function(); }

private:
    // Data members
    function_type       m_function;
};

// ************************************************************************** //
// **************                class_test_case               ************** //
// ************************************************************************** //

template<class UserTestCase>
class class_test_case : public test_case {
public:
    typedef void  (UserTestCase::*function_type)();

    // Constructor
    class_test_case( function_type f_, c_string_literal name_, boost::shared_ptr<UserTestCase>& user_test_case_ )
    : test_case( name_, 1 ), m_user_test_case( user_test_case_ ), m_function( f_ )
    {}

private:
    // test case implementation
    void                do_run()
    {
        if( (!!m_user_test_case) && m_function )
            ((*m_user_test_case).*m_function)();
    }
    void                do_destroy()
    {
        m_user_test_case.reset(); // t ofree the reference to the shared use test case instance
    }

    // Data members
    boost::shared_ptr<UserTestCase> m_user_test_case;
    function_type       m_function;
};

// ************************************************************************** //
// **************        parametrized_function_test_case       ************** //
// ************************************************************************** //

template <typename ParamIterator, typename ParameterType>
class parametrized_function_test_case : public test_case {
public:
    typedef void  (*function_type)( ParameterType );

    // Constructor
    parametrized_function_test_case( function_type f_, c_string_literal name_,
                                     ParamIterator const& par_begin_, ParamIterator const& par_end_ )
    : test_case( name_ ), m_first_parameter( par_begin_ ), m_last_parameter( par_end_ ), m_function( f_ )
    {
       // the typecasts are here to keep Borland C++ Builder 5 happy, for other compilers they have no effect:
       p_stages_amount.set( detail::distance( (ParamIterator)par_begin_, (ParamIterator)par_end_ ) );
    }

    // test case implementation
    void                do_init()       { m_curr_parameter = m_first_parameter; }
    void                do_run()        { m_function( *m_curr_parameter++ ); }

private:
    // Data members
    ParamIterator       m_first_parameter;
    ParamIterator       m_last_parameter;
    ParamIterator       m_curr_parameter;

    function_type       m_function;
};

// ************************************************************************** //
// **************         parametrized_class_test_case         ************** //
// ************************************************************************** //

template <class UserTestCase, class ParamIterator, typename ParameterType>
class parametrized_class_test_case : public test_case {
public:
    typedef void  (UserTestCase::*function_type)( ParameterType );

    // Constructor
    parametrized_class_test_case( function_type f_, c_string_literal name_, boost::shared_ptr<UserTestCase>& user_test_case_,
                                  ParamIterator const& par_begin_, ParamIterator const& par_end_ )
    : test_case( name_ ), m_first_parameter( par_begin_ ), m_last_parameter( par_end_ ),
      m_user_test_case( user_test_case_ ), m_function( f_ )
    {
       // the typecasts are here to keep Borland C++ Builder 5 happy, for other compilers they have no effect:
       p_stages_amount.set( detail::distance( (ParamIterator)par_begin_, (ParamIterator)par_end_ ) );
    }

    // test case implementation
    void                do_init()       { m_curr_parameter = m_first_parameter; }
    void                do_run()        { ((*m_user_test_case).*m_function)( *m_curr_parameter++ ); }
    void                do_destroy()    { m_user_test_case.reset(); }

private:
    // Data members
    ParamIterator       m_first_parameter;
    ParamIterator       m_last_parameter;
    ParamIterator       m_curr_parameter;

    boost::shared_ptr<UserTestCase> m_user_test_case;
    function_type       m_function;
};

// ************************************************************************** //
// **************                  test_suite                  ************** //
// ************************************************************************** //

class test_suite : public test_case {
public:
    // Constructor
    explicit test_suite( c_string_literal name_ = "Master" );

    // Destructor
    virtual             ~test_suite();

    // test case list management
    void                add( test_case* tc_, unit_test_counter expected_failures_ = 0, int timeout_ = 0 );

    // access methods
    unit_test_counter   size() const;
    c_string_literal    type() const;

    // test case implementation
    void                do_init();
    void                do_run();

private:
    // Data members
    struct Impl;
    boost::shared_ptr<Impl> m_pimpl;
};

// ************************************************************************** //
// **************               object generators              ************** //
// ************************************************************************** //

namespace detail {

c_string_literal normalize_test_case_name( std::string& name_ );

} // namespace detail

//____________________________________________________________________________//

inline test_case*
create_test_case( void (*fct_)(), std::string name_ )
{
    return new function_test_case( fct_, detail::normalize_test_case_name( name_ ) );
}

//____________________________________________________________________________//

template<class UserTestCase>
inline test_case*
create_test_case( void (UserTestCase::*fct_)(), std::string name_, boost::shared_ptr<UserTestCase>& user_test_case_ )
{
    return new class_test_case<UserTestCase>( fct_, detail::normalize_test_case_name( name_ ), user_test_case_ );
}

//____________________________________________________________________________//

template<typename ParamIterator, typename ParamType>
inline test_case*
create_test_case( void (*fct_)( ParamType ), std::string name_, ParamIterator const& par_begin_, ParamIterator const& par_end_ )
{
    return new parametrized_function_test_case<ParamIterator,ParamType>(
        fct_, detail::normalize_test_case_name( name_ ), par_begin_, par_end_ );
}

//____________________________________________________________________________//

template<class UserTestCase, typename ParamIterator, typename ParamType>
inline test_case*
create_test_case( void (UserTestCase::*fct_)( ParamType ), std::string name_, boost::shared_ptr<UserTestCase>& user_test_case_,
                  ParamIterator const& par_begin_, ParamIterator const& par_end_ )
{
    return new parametrized_class_test_case<UserTestCase,ParamIterator,ParamType>(
        fct_, detail::normalize_test_case_name( name_ ), user_test_case_, par_begin_, par_end_ );
}

//____________________________________________________________________________//

} // unit_test_framework

} // namespace boost

// ***************************************************************************
//  Revision History :
//
//  $Log$
//  Revision 1.12  2002/12/08 17:51:04  rogeeff
//  notion of number of stages is separated from number of test cases, so that
//  parameterized test case in reported as one test case
//  fixed bug in both parameterized function/class test cases with not iterating
//  parameter iterator if exception occured
//  switched to use c_string_literal
//
//  Revision 1.11  2002/11/02 19:31:04  rogeeff
//  merged into the main trank
//

// ***************************************************************************

#endif // BOOST_UNIT_TEST_SUITE_HPP

<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/neural_layer.hpp"

#include "dll/util/timers.hpp" // for auto_timer

namespace dll {

/*!
 * \brief Standard convolutional layer of neural network.
 */
template <typename Desc>
struct conv_same_layer final : neural_layer<conv_same_layer<Desc>, Desc> {
    using desc      = Desc;
    using weight    = typename desc::weight;
    using this_type = conv_same_layer<desc>;
    using base_type = neural_layer<this_type, desc>;

    static constexpr size_t NV1 = desc::NV1; ///< The first dimension of the visible units
    static constexpr size_t NV2 = desc::NV2; ///< The second dimension of the visible units
    static constexpr size_t NW1 = desc::NW1; ///< The first dimension of the filter
    static constexpr size_t NW2 = desc::NW2; ///< The second dimension of the filter
    static constexpr size_t NC  = desc::NC;  ///< The number of input channels
    static constexpr size_t K   = desc::K;   ///< The number of filters

    static constexpr size_t NH1 = NV1; //By definition
    static constexpr size_t NH2 = NV2; //By definition

    static constexpr size_t P1 = (NW1 - 1) / 2;
    static constexpr size_t P2 = (NW2 - 1) / 2;

    static constexpr auto activation_function = desc::activation_function;
    static constexpr auto w_initializer       = desc::w_initializer;
    static constexpr auto b_initializer       = desc::b_initializer;

    static_assert(NW1 % 2 == 1, "conv_same_layer only works with odd-sized filters");
    static_assert(NW2 % 2 == 1, "conv_same_layer only works with odd-sized filters");

    using input_one_t  = etl::fast_dyn_matrix<weight, NC, NV1, NV2>;
    using output_one_t = etl::fast_dyn_matrix<weight, K, NH1, NH2>;
    using input_t      = std::vector<input_one_t>;
    using output_t     = std::vector<output_one_t>;

    using w_type = etl::fast_matrix<weight, K, NC, NW1, NW2>;
    using b_type = etl::fast_matrix<weight, K>;

    //Weights and biases
    w_type w; //!< Weights
    b_type b; //!< Hidden biases

    //Backup weights and biases
    std::unique_ptr<w_type> bak_w; //!< Backup Weights
    std::unique_ptr<b_type> bak_b; //!< Backup Hidden biases

    /*!
     * \brief Initialize a conv layer with basic weights.
     */
    conv_same_layer() : base_type() {
        initializer_function<w_initializer>::initialize(w, input_size(), output_size());
        initializer_function<b_initializer>::initialize(b, input_size(), output_size());
    }

    static constexpr std::size_t input_size() noexcept {
        return NC * NV1 * NV2;
    }

    static constexpr std::size_t output_size() noexcept {
        return K * NH1 * NH2;
    }

    static constexpr std::size_t parameters() noexcept {
        return K * NW1 * NW2;
    }

    static std::string to_short_string() {
        char buffer[1024];
        snprintf(buffer, 1024, "Conv(same): %lux%lux%lu -> (%lux%lux%lu) -> %s -> %lux%lux%lu", NC, NV1, NV2, K, NW1, NW2, to_string(activation_function).c_str(), K, NH1, NH2);
        return {buffer};
    }

    template<typename H>
    void activate_hidden(H&& output, const input_one_t& v) const {
        dll::auto_timer timer("conv_same:forward");

        auto b_rep = etl::force_temporary(etl::rep<NH1, NH2>(b));

        etl::reshape<1, K, NH1, NH2>(output) = etl::conv_4d_valid_flipped<1, 1, P1, P2>(etl::reshape<1, NC, NV1, NV2>(v), w);

        output = f_activate<activation_function>(b_rep + output);
    }

    template <typename H, typename V>
    void activate_hidden(H&& output, const V& v) const {
        dll::auto_timer timer("conv_same:forward");

        decltype(auto) converted = converter_one<V, input_one_t>::convert(*this, v);
        activate_hidden(output, converted);
    }

    template <typename H1, typename V>
    void batch_activate_hidden(H1&& output, const V& v) const {
        dll::auto_timer timer("conv_same:forward_batch");
        output = etl::conv_4d_valid_flipped<1, 1, P1, P2>(v, w);

        static constexpr const auto batch_size = etl::decay_traits<H1>::template dim<0>();

        auto b_rep = etl::force_temporary(etl::rep_l<batch_size>(etl::rep<NH1, NH2>(b)));

        output = f_activate<activation_function>(b_rep + output);
    }

    template <typename Input>
    output_one_t prepare_one_output() const {
        return {};
    }

    template <typename Input>
    static output_t prepare_output(std::size_t samples) {
        return output_t{samples};
    }

    template<typename DRBM>
    static void dyn_init(DRBM& dyn){
        dyn.init_layer(NC, NV1, NV2, K, NW1, NW2);
    }

    /*!
     * \brief Adapt the errors, called before backpropagation of the errors.
     *
     * This must be used by layers that have both an activation fnction and a non-linearity.
     *
     * \param context the training context
     */
    template<typename C>
    void adapt_errors(C& context) const {
        dll::auto_timer timer("conv_same:adapt_errors");

        if(activation_function != function::IDENTITY){
            context.errors = f_derivative<activation_function>(context.output) >> context.errors;
        }
    }

    /*!
     * \brief Backpropagate the errors to the previous layers
     * \param output The ETL expression into which write the output
     * \param context The training context
     */
    template<typename H, typename C>
    void backward_batch(H&& output, C& context) const {
        dll::auto_timer timer("conv_same:backward_batch");

        cpp_unused(output);
        cpp_unused(context);

        output = etl::conv_4d_valid_back_flipped<1, 1, P1, P2>(context.errors, w);
    }

    /*!
     * \brief Compute the gradients for this layer, if any
     * \param context The trainng context
     */
    template<typename C>
    void compute_gradients(C& context) const {
        dll::auto_timer timer("conv_same:compute_gradients");

        context.w_grad = etl::conv_4d_valid_filter_flipped<1, 1, P1, P2>(context.input, context.errors);
        context.b_grad = etl::mean_r(etl::sum_l(context.errors));
    }
};

//Allow odr-use of the constexpr static members

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NV1;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NV2;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NH1;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NH2;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NC;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NW1;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NW2;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::K;

// Declare the traits for the Layer

template<typename Desc>
struct layer_base_traits<conv_same_layer<Desc>> {
    static constexpr bool is_neural     = true;  ///< Indicates if the layer is a neural layer
    static constexpr bool is_dense      = false;  ///< Indicates if the layer is dense
    static constexpr bool is_conv       = true; ///< Indicates if the layer is convolutional
    static constexpr bool is_deconv     = false; ///< Indicates if the layer is deconvolutional
    static constexpr bool is_standard   = true;  ///< Indicates if the layer is standard
    static constexpr bool is_rbm        = false;  ///< Indicates if the layer is RBM
    static constexpr bool is_pooling    = false; ///< Indicates if the layer is a pooling layer
    static constexpr bool is_unpooling  = false; ///< Indicates if the layer is an unpooling laye
    static constexpr bool is_transform  = false; ///< Indicates if the layer is a transform layer
    static constexpr bool is_patches    = false; ///< Indicates if the layer is a patches layer
    static constexpr bool is_augment    = false; ///< Indicates if the layer is an augment layer
    static constexpr bool is_dynamic    = false; ///< Indicates if the layer is dynamic
    static constexpr bool pretrain_last = false; ///< Indicates if the layer is dynamic
    static constexpr bool sgd_supported = true;  ///< Indicates if the layer is supported by SGD
};

/*!
 * \brief Specialization of the sgd_context for conv_same_layer
 */
template <typename DBN, typename Desc>
struct sgd_context<DBN, conv_same_layer<Desc>> {
    using layer_t = conv_same_layer<Desc>;
    using weight  = typename layer_t::weight;

    static constexpr size_t NV1 = layer_t::NV1;
    static constexpr size_t NV2 = layer_t::NV2;
    static constexpr size_t NH1 = layer_t::NH1;
    static constexpr size_t NH2 = layer_t::NH2;
    static constexpr size_t NW1 = layer_t::NW1;
    static constexpr size_t NW2 = layer_t::NW2;
    static constexpr size_t NC  = layer_t::NC;
    static constexpr size_t K   = layer_t::K;

    static constexpr auto batch_size = DBN::batch_size;

    etl::fast_matrix<weight, K, NC, NW1, NW2> w_grad;
    etl::fast_matrix<weight, K> b_grad;

    etl::fast_matrix<weight, K, NC, NW1, NW2> w_inc;
    etl::fast_matrix<weight, K> b_inc;

    etl::fast_matrix<weight, batch_size, NC, NV1, NV2> input;
    etl::fast_matrix<weight, batch_size, K, NH1, NH2> output;
    etl::fast_matrix<weight, batch_size, K, NH1, NH2> errors;

    sgd_context()
            : w_inc(0.0), b_inc(0.0), output(0.0), errors(0.0) {}
};

} //end of dll namespace
<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

#include "dll/neural_layer.hpp"

#include "dll/util/timers.hpp" // for auto_timer

namespace dll {

/*!
 * \brief Standard convolutional layer of neural network.
 */
template <typename Desc>
struct conv_same_layer final : neural_layer<conv_same_layer<Desc>, Desc> {
    using desc      = Desc;
    using weight    = typename desc::weight;
    using this_type = conv_same_layer<desc>;
    using base_type = neural_layer<this_type, desc>;

    static constexpr size_t NV1 = desc::NV1; ///< The first dimension of the visible units
    static constexpr size_t NV2 = desc::NV2; ///< The second dimension of the visible units
    static constexpr size_t NW1 = desc::NW1; ///< The first dimension of the filter
    static constexpr size_t NW2 = desc::NW2; ///< The second dimension of the filter
    static constexpr size_t NC  = desc::NC;  ///< The number of input channels
    static constexpr size_t K   = desc::K;   ///< The number of filters

    static constexpr size_t NH1 = NV1; //By definition
    static constexpr size_t NH2 = NV2; //By definition

    static constexpr size_t P1 = (NW1 - 1) / 2;
    static constexpr size_t P2 = (NW2 - 1) / 2;

    static constexpr auto activation_function = desc::activation_function;
    static constexpr auto w_initializer       = desc::w_initializer;
    static constexpr auto b_initializer       = desc::b_initializer;

    static_assert(NW1 % 2 == 1, "conv_same_layer only works with odd-sized filters");
    static_assert(NW2 % 2 == 1, "conv_same_layer only works with odd-sized filters");

    using input_one_t  = etl::fast_dyn_matrix<weight, NC, NV1, NV2>;
    using output_one_t = etl::fast_dyn_matrix<weight, K, NH1, NH2>;
    using input_t      = std::vector<input_one_t>;
    using output_t     = std::vector<output_one_t>;

    using w_type = etl::fast_matrix<weight, K, NC, NW1, NW2>;
    using b_type = etl::fast_matrix<weight, K>;

    //Weights and biases
    w_type w; //!< Weights
    b_type b; //!< Hidden biases

    //Backup weights and biases
    std::unique_ptr<w_type> bak_w; //!< Backup Weights
    std::unique_ptr<b_type> bak_b; //!< Backup Hidden biases

    /*!
     * \brief Initialize a conv layer with basic weights.
     */
    conv_same_layer() : base_type() {
        initializer_function<w_initializer>::initialize(w, input_size(), output_size());
        initializer_function<b_initializer>::initialize(b, input_size(), output_size());
    }

    static constexpr std::size_t input_size() noexcept {
        return NC * NV1 * NV2;
    }

    static constexpr std::size_t output_size() noexcept {
        return K * NH1 * NH2;
    }

    static constexpr std::size_t parameters() noexcept {
        return K * NW1 * NW2;
    }

    static std::string to_short_string() {
        char buffer[1024];
        snprintf(buffer, 1024, "Conv(same): %lux%lux%lu -> (%lux%lux%lu) -> %s -> %lux%lux%lu", NC, NV1, NV2, K, NW1, NW2, to_string(activation_function).c_str(), K, NH1, NH2);
        return {buffer};
    }

    template<typename H>
    void activate_hidden(H&& output, const input_one_t& v) const {
        dll::auto_timer timer("conv_same:forward");

        auto b_rep = etl::force_temporary(etl::rep<NH1, NH2>(b));

        etl::reshape<1, K, NH1, NH2>(output) = etl::conv_4d_valid_flipped<1, 1, P1, P2>(etl::reshape<1, NC, NV1, NV2>(v), w);

        output = f_activate<activation_function>(b_rep + output);
    }

    template <typename H, typename V>
    void activate_hidden(H&& output, const V& v) const {
        dll::auto_timer timer("conv_same:forward");

        decltype(auto) converted = converter_one<V, input_one_t>::convert(*this, v);
        activate_hidden(output, converted);
    }

    template <typename H1, typename V>
    void batch_activate_hidden(H1&& output, const V& v) const {
        dll::auto_timer timer("conv_same:forward_batch");
        output = etl::conv_4d_valid_flipped<1, 1, P1, P2>(v, w);

        static constexpr const auto batch_size = etl::decay_traits<H1>::template dim<0>();

        auto b_rep = etl::force_temporary(etl::rep_l<batch_size>(etl::rep<NH1, NH2>(b)));

        output = f_activate<activation_function>(b_rep + output);
    }

    template <typename Input>
    output_one_t prepare_one_output() const {
        return {};
    }

    template <typename Input>
    static output_t prepare_output(std::size_t samples) {
        return output_t{samples};
    }

    template<typename DRBM>
    static void dyn_init(DRBM& dyn){
        dyn.init_layer(NC, NV1, NV2, K, NW1, NW2);
    }

    /*!
     * \brief Adapt the errors, called before backpropagation of the errors.
     *
     * This must be used by layers that have both an activation fnction and a non-linearity.
     *
     * \param context the training context
     */
    template<typename C>
    void adapt_errors(C& context) const {
        dll::auto_timer timer("conv_same:adapt_errors");

        if(activation_function != function::IDENTITY){
            context.errors = f_derivative<activation_function>(context.output) >> context.errors;
        }
    }

    /*!
     * \brief Backpropagate the errors to the previous layers
     * \param output The ETL expression into which write the output
     * \param context The training context
     */
    template<typename H, typename C>
    void backward_batch(H&& output, C& context) const {
        dll::auto_timer timer("conv_same:backward_batch");

        output = etl::conv_4d_valid_back_flipped<1, 1, P1, P2>(context.errors, w);
    }

    /*!
     * \brief Compute the gradients for this layer, if any
     * \param context The trainng context
     */
    template<typename C>
    void compute_gradients(C& context) const {
        dll::auto_timer timer("conv_same:compute_gradients");

        context.w_grad = etl::conv_4d_valid_filter_flipped<1, 1, P1, P2>(context.input, context.errors);
        context.b_grad = etl::mean_r(etl::sum_l(context.errors));
    }
};

//Allow odr-use of the constexpr static members

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NV1;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NV2;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NH1;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NH2;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NC;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NW1;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::NW2;

template <typename Desc>
const std::size_t conv_same_layer<Desc>::K;

// Declare the traits for the Layer

template<typename Desc>
struct layer_base_traits<conv_same_layer<Desc>> {
    static constexpr bool is_neural     = true;  ///< Indicates if the layer is a neural layer
    static constexpr bool is_dense      = false;  ///< Indicates if the layer is dense
    static constexpr bool is_conv       = true; ///< Indicates if the layer is convolutional
    static constexpr bool is_deconv     = false; ///< Indicates if the layer is deconvolutional
    static constexpr bool is_standard   = true;  ///< Indicates if the layer is standard
    static constexpr bool is_rbm        = false;  ///< Indicates if the layer is RBM
    static constexpr bool is_pooling    = false; ///< Indicates if the layer is a pooling layer
    static constexpr bool is_unpooling  = false; ///< Indicates if the layer is an unpooling laye
    static constexpr bool is_transform  = false; ///< Indicates if the layer is a transform layer
    static constexpr bool is_patches    = false; ///< Indicates if the layer is a patches layer
    static constexpr bool is_augment    = false; ///< Indicates if the layer is an augment layer
    static constexpr bool is_dynamic    = false; ///< Indicates if the layer is dynamic
    static constexpr bool pretrain_last = false; ///< Indicates if the layer is dynamic
    static constexpr bool sgd_supported = true;  ///< Indicates if the layer is supported by SGD
};

/*!
 * \brief Specialization of the sgd_context for conv_same_layer
 */
template <typename DBN, typename Desc>
struct sgd_context<DBN, conv_same_layer<Desc>> {
    using layer_t = conv_same_layer<Desc>;
    using weight  = typename layer_t::weight;

    static constexpr size_t NV1 = layer_t::NV1;
    static constexpr size_t NV2 = layer_t::NV2;
    static constexpr size_t NH1 = layer_t::NH1;
    static constexpr size_t NH2 = layer_t::NH2;
    static constexpr size_t NW1 = layer_t::NW1;
    static constexpr size_t NW2 = layer_t::NW2;
    static constexpr size_t NC  = layer_t::NC;
    static constexpr size_t K   = layer_t::K;

    static constexpr auto batch_size = DBN::batch_size;

    etl::fast_matrix<weight, K, NC, NW1, NW2> w_grad;
    etl::fast_matrix<weight, K> b_grad;

    etl::fast_matrix<weight, K, NC, NW1, NW2> w_inc;
    etl::fast_matrix<weight, K> b_inc;

    etl::fast_matrix<weight, batch_size, NC, NV1, NV2> input;
    etl::fast_matrix<weight, batch_size, K, NH1, NH2> output;
    etl::fast_matrix<weight, batch_size, K, NH1, NH2> errors;

    sgd_context()
            : w_inc(0.0), b_inc(0.0), output(0.0), errors(0.0) {}
};

} //end of dll namespace
<|endoftext|>