<commit_before>// netfortune brings fortunes for everyone, everywhere
// Copyright © 2017 Christian Rapp
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the organization nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY  ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <csignal>
#include <ctime>
#include <functional>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include <vector>

#include <boost/asio.hpp>
#include <boost/filesystem.hpp>

#include <sqlite3.h>

#include "cpptoml/cpptoml.h"
#include "spdlog/spdlog.h"

#include "config_netfortune.hpp"
#include "configuration.hpp"
#include "fserver.hpp"
#include "utility.hpp"

int main()
{
    std::shared_ptr<cpptoml::table> cfg = nullptr;
    std::string cfg_file = "netfortune-server.toml";
    if (!boost::filesystem::exists(cfg_file)) {
        if (!boost::filesystem::exists("/etc/" + cfg_file)) {
            std::cerr << "Can not find config file netfortune-server.toml"
                      << std::endl;
            return 1;
        }
        cfg_file = "/etc/" + cfg_file;
    }
    try {
        cfg = cpptoml::parse_file("netfortune-server.toml");
        std::cout << (*cfg) << std::endl;
    } catch (const cpptoml::parse_exception &ex) {
        std::cerr << "Could not parse config file" << std::endl;
        std::cerr << ex.what() << std::endl;
        return 1;
    }

    namespace nc = netfortune_configuration;
    // check if config file was changed
    bool config_changed = cfg->get_as<bool>(nc::CHANGED_CONFIG)
                              .value_or(nc::CHANGED_CONFIG_DEFAULT);
    if (!config_changed) {
        std::cerr
            << "You have to change the configuration file for netfortune server"
            << std::endl;
        return 1;
    }
    // TODO: Add multiple sinks to our logger
    // std::vector<spdlog::sink_ptr> sinks;
    //sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_st>());
    //sinks.push_back(std::make_shared<spdlog::sinks::daily_file_sink_st>("logfile", "txt", 23, 59));
    // auto combined_logger = std::make_shared<spdlog::logger>("name",
    // begin(sinks), end(sinks));
    ////register it if you need to access it globally
    // spdlog::register_logger(combined_logger);
    // asynchronous logging
    spdlog::set_async_mode(512, spdlog::async_overflow_policy::discard_log_msg);
    auto logger = spdlog::stdout_color_mt("multi_logger");
    logger->set_level(spdlog::level::level_enum::debug);
    std::stringstream ss;
    ss << NETFORTUNE_VERSION_MAJOR << "." << NETFORTUNE_VERSION_MINOR;
#ifdef netfortune_VERSION_PATCH
    ss << "." << NETFORTUNE_VERSION_PATCH;
#endif

    logger->info("Netfortune Server Version " + ss.str());

    boost::asio::io_service io_service;

    boost::asio::signal_set signal_set(io_service, SIGINT, SIGTERM);
    signal_set.async_wait(
        [&io_service, &logger](const boost::system::error_code &ec ATTR_UNUSED,
                               int signal_number) {
            std::unordered_map<int, std::string> signal_name = {
                {SIGINT, "SIGINT"}, {SIGTERM, "SIGTERM"}};
            logger->debug("Got signal " + signal_name.at(signal_number) +
                          "; stopping io_service.");
            io_service.stop();
        });

    std::vector<std::thread> thread_pool;

    try {
        auto s =
            netfortune_utility::toml_stringify(nc::SERVER, nc::SERVER_THREADS);
        auto nr_threads = cfg->get_qualified_as<unsigned int>(
                                 netfortune_utility::toml_stringify(
                                     nc::SERVER, nc::SERVER_THREADS))
                              .value_or(nc::SERVER_THREADS_DEFAULT);
        if (nr_threads == 0) {
            logger->error("Zero threads do not make any sense");
            return 1;
        }

        int ts = sqlite3_threadsafe();
        if (ts == 0) {
            logger->warn(
                "The installed SQlite Library does not support "
                " multithreading. netfortune will only use one thread.");
            nr_threads = 1;
        }

        logger->debug("Will spawn " + std::to_string(nr_threads) +
                      " additional threads");

        FServer server(io_service, std::move(cfg));

        logger->info("Main thread id " + netfortune_utility::op_to_string(
                                             std::this_thread::get_id()));
        for (unsigned int i = 0; i < (nr_threads - 1); i++) {
            logger->debug("Creating thread number " + std::to_string(0));
            thread_pool.emplace_back([&io_service, &logger, i]() {
                logger->info("Thread " + std::to_string(i) + " id: " +
                             netfortune_utility::op_to_string(
                                 std::this_thread::get_id()));
                io_service.run();
            });
        }
        // Main thread also calls run()
        io_service.run();
        for (auto &t : thread_pool) {
            t.join();
        }
    } catch (const std::exception &ex) {
        logger->error(ex.what());
    }

    spdlog::drop_all();

    // boost::asio::io_service io;

    // try {
    // boost::asio::io_service io_service;

    // tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13));

    // for (;;) {
    // tcp::socket socket(io_service);
    //acceptor.accept(socket);

    // std::string message = make_daytime_string();
    //message.erase(std::remove(message.begin(), message.end(), '\n'),
    //message.end());
    // nlohmann::json j;
    // j["daytime"] = message;

    // boost::system::error_code ignored_error;
    //boost::asio::write(socket, boost::asio::buffer(j.dump(2)),
    // ignored_error);
    //}
    //} catch (std::exception& e) {
    //std::cerr << e.what() << std::endl;
    //}

    return 0;
}
<commit_msg>reformat main.cpp<commit_after>// netfortune brings fortunes for everyone, everywhere
// Copyright © 2017 Christian Rapp
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the organization nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY  ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <csignal>
#include <ctime>
#include <functional>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>
#include <vector>

#include <boost/asio.hpp>
#include <boost/filesystem.hpp>

#include <sqlite3.h>

#include "cpptoml/cpptoml.h"
#include "spdlog/spdlog.h"

#include "config_netfortune.hpp"
#include "configuration.hpp"
#include "fserver.hpp"
#include "utility.hpp"

int main()
{
    std::shared_ptr<cpptoml::table> cfg = nullptr;
    std::string cfg_file = "netfortune-server.toml";
    if (!boost::filesystem::exists(cfg_file)) {
        if (!boost::filesystem::exists("/etc/" + cfg_file)) {
            std::cerr << "Can not find config file netfortune-server.toml"
                      << std::endl;
            return 1;
        }
        cfg_file = "/etc/" + cfg_file;
    }
    try {
        cfg = cpptoml::parse_file("netfortune-server.toml");
        std::cout << (*cfg) << std::endl;
    } catch (const cpptoml::parse_exception &ex) {
        std::cerr << "Could not parse config file" << std::endl;
        std::cerr << ex.what() << std::endl;
        return 1;
    }

    namespace nc = netfortune_configuration;
    // check if config file was changed
    bool config_changed = cfg->get_as<bool>(nc::CHANGED_CONFIG)
                              .value_or(nc::CHANGED_CONFIG_DEFAULT);
    if (!config_changed) {
        std::cerr
            << "You have to change the configuration file for netfortune server"
            << std::endl;
        return 1;
    }
    // TODO: Add multiple sinks to our logger
    // std::vector<spdlog::sink_ptr> sinks;
    // sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_st>());
    // sinks.push_back(std::make_shared<spdlog::sinks::daily_file_sink_st>("logfile",
    // "txt", 23, 59));
    // auto combined_logger = std::make_shared<spdlog::logger>("name",
    // begin(sinks), end(sinks));
    ////register it if you need to access it globally
    // spdlog::register_logger(combined_logger);
    // asynchronous logging
    spdlog::set_async_mode(512, spdlog::async_overflow_policy::discard_log_msg);
    auto logger = spdlog::stdout_color_mt("multi_logger");
    logger->set_level(spdlog::level::level_enum::debug);
    std::stringstream ss;
    ss << NETFORTUNE_VERSION_MAJOR << "." << NETFORTUNE_VERSION_MINOR;
#ifdef netfortune_VERSION_PATCH
    ss << "." << NETFORTUNE_VERSION_PATCH;
#endif

    logger->info("Netfortune Server Version " + ss.str());

    boost::asio::io_service io_service;

    boost::asio::signal_set signal_set(io_service, SIGINT, SIGTERM);
    signal_set.async_wait(
        [&io_service, &logger](const boost::system::error_code &ec ATTR_UNUSED,
                               int signal_number) {
            std::unordered_map<int, std::string> signal_name = {
                {SIGINT, "SIGINT"}, {SIGTERM, "SIGTERM"}};
            logger->debug("Got signal " + signal_name.at(signal_number) +
                          "; stopping io_service.");
            io_service.stop();
        });

    std::vector<std::thread> thread_pool;

    try {
        auto s =
            netfortune_utility::toml_stringify(nc::SERVER, nc::SERVER_THREADS);
        auto nr_threads = cfg->get_qualified_as<unsigned int>(
                                 netfortune_utility::toml_stringify(
                                     nc::SERVER, nc::SERVER_THREADS))
                              .value_or(nc::SERVER_THREADS_DEFAULT);
        if (nr_threads == 0) {
            logger->error("Zero threads do not make any sense");
            return 1;
        }

        int ts = sqlite3_threadsafe();
        if (ts == 0) {
            logger->warn(
                "The installed SQlite Library does not support "
                " multithreading. netfortune will only use one thread.");
            nr_threads = 1;
        }

        logger->debug("Will spawn " + std::to_string(nr_threads) +
                      " additional threads");

        FServer server(io_service, std::move(cfg));

        logger->info("Main thread id " + netfortune_utility::op_to_string(
                                             std::this_thread::get_id()));
        for (unsigned int i = 0; i < (nr_threads - 1); i++) {
            logger->debug("Creating thread number " + std::to_string(0));
            thread_pool.emplace_back([&io_service, &logger, i]() {
                logger->info("Thread " + std::to_string(i) + " id: " +
                             netfortune_utility::op_to_string(
                                 std::this_thread::get_id()));
                io_service.run();
            });
        }
        // Main thread also calls run()
        io_service.run();
        for (auto &t : thread_pool) {
            t.join();
        }
    } catch (const std::exception &ex) {
        logger->error(ex.what());
    }

    spdlog::drop_all();

    // boost::asio::io_service io;

    // try {
    // boost::asio::io_service io_service;

    // tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 13));

    // for (;;) {
    // tcp::socket socket(io_service);
    // acceptor.accept(socket);

    // std::string message = make_daytime_string();
    // message.erase(std::remove(message.begin(), message.end(), '\n'),
    // message.end());
    // nlohmann::json j;
    // j["daytime"] = message;

    // boost::system::error_code ignored_error;
    // boost::asio::write(socket, boost::asio::buffer(j.dump(2)),
    // ignored_error);
    //}
    //} catch (std::exception& e) {
    // std::cerr << e.what() << std::endl;
    //}

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010-2012 Jeremy Lainé
 * Contact: http://code.google.com/p/qdjango/
 *
 * This file is part of the QDjango Library.
 *
 * 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.
 */

#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
#include <QSqlDriver>
#include <QSqlError>
#include <QSqlQuery>
#include <QStringList>
#include <QThread>

#include "QDjango.h"

static const char *connectionPrefix = "_qdjango_";

QMap<QByteArray, QDjangoMetaModel> globalMetaModels = QMap<QByteArray, QDjangoMetaModel>();
static QDjangoDatabase *globalDatabase = 0;
static bool globalDebugEnabled = false;

/// \cond

QDjangoDatabase::QDjangoDatabase(QObject *parent)
    : QObject(parent), connectionId(0)
{
}

void QDjangoDatabase::threadFinished()
{
    QThread *thread = qobject_cast<QThread*>(sender());
    if (!thread)
        return;

    // cleanup database connection for the thread
    QMutexLocker locker(&mutex);
    disconnect(thread, SIGNAL(finished()), this, SLOT(threadFinished()));
    const QString connectionName = copies.value(thread).connectionName();
    copies.remove(thread);
    if (connectionName.startsWith(QLatin1String(connectionPrefix)))
        QSqlDatabase::removeDatabase(connectionName);
}

static void closeDatabase()
{
    delete globalDatabase;
}

static void initDatabase(QSqlDatabase db)
{
    if (db.driverName() == QLatin1String("QSQLITE")) {
        // enable foreign key constraint handling
        QDjangoQuery query(db);
        query.prepare("PRAGMA foreign_keys=on");
        query.exec();
    }
}

QDjangoQuery::QDjangoQuery(QSqlDatabase db)
    : QSqlQuery(db)
{
}

void QDjangoQuery::addBindValue(const QVariant &val, QSql::ParamType paramType)
{
    // this hack is required so that we do not store a mix of local
    // and UTC times
    if (val.type() == QVariant::DateTime)
        QSqlQuery::addBindValue(val.toDateTime().toLocalTime(), paramType);
    else
        QSqlQuery::addBindValue(val, paramType);
}

bool QDjangoQuery::exec()
{
    if (globalDebugEnabled) {
        qDebug() << "SQL query" << lastQuery();
        QMapIterator<QString, QVariant> i(boundValues());
        while (i.hasNext()) {
            i.next();
            qDebug() << "SQL   " << i.key().toLatin1().data() << "="
                     << i.value().toString().toLatin1().data();
        }
    }
    if (!QSqlQuery::exec()) {
        if (globalDebugEnabled)
            qWarning() << "SQL error" << lastError();
        return false;
    }
    return true;
}

bool QDjangoQuery::exec(const QString &query)
{
    if (globalDebugEnabled)
        qDebug() << "SQL query" << query;
    if (!QSqlQuery::exec(query)) {
        if (globalDebugEnabled)
            qWarning() << "SQL error" << lastError();
        return false;
    }
    return true;
}

/// \endcond

/*!
    \mainpage

    QDjango is a simple yet powerful Object Relation Mapper (ORM) built
    on top of the Qt library. Where possible it tries to follow django's
    ORM API, hence its name.

    \sa QDjango
    \sa QDjangoModel
    \sa QDjangoWhere
    \sa QDjangoQuerySet
*/

/*!
    Returns the database used by QDjango.

    If you call this method from any thread but the application's main thread,
    a new connection to the database will be created. The connection will
    automatically be torn down once the thread finishes.

    \sa setDatabase()
*/
QSqlDatabase QDjango::database()
{
    if (!globalDatabase)
        return QSqlDatabase();

    // if we are in the main thread, return reference connection
    QThread *thread = QThread::currentThread();
    if (thread == globalDatabase->thread())
        return globalDatabase->reference;

    // if we have a connection for this thread, return it
    QMutexLocker locker(&globalDatabase->mutex);
    if (globalDatabase->copies.contains(thread))
        return globalDatabase->copies[thread];

    // create a new connection for this thread
    QObject::connect(thread, SIGNAL(finished()), globalDatabase, SLOT(threadFinished()));
    QSqlDatabase db = QSqlDatabase::cloneDatabase(globalDatabase->reference,
        QLatin1String(connectionPrefix) + QString::number(globalDatabase->connectionId++));
    db.open();
    initDatabase(db);
    globalDatabase->copies.insert(thread, db);
    return db;
}

/*!
    Sets the database used by QDjango.

    You must call this method from your application's main thread.

    \sa database()
*/
void QDjango::setDatabase(QSqlDatabase database)
{
    if (database.driverName() != QLatin1String("QSQLITE") &&
        database.driverName() != QLatin1String("QSQLITE2") &&
        database.driverName() != QLatin1String("QMYSQL") &&
        database.driverName() != QLatin1String("QPSQL"))
    {
        qWarning() << "Unsupported database driver" << database.driverName();
    }
    if (!globalDatabase)
    {
        globalDatabase = new QDjangoDatabase();
        qAddPostRoutine(closeDatabase);
    }
    initDatabase(database);
    globalDatabase->reference = database;
}

/*!
    Returns whether debugging information should be printed.

    \sa setDebugEnabled()
*/
bool QDjango::isDebugEnabled()
{
    return globalDebugEnabled;
}

/*!
    Sets whether debugging information should be printed.

    \sa isDebugEnabled()
*/
void QDjango::setDebugEnabled(bool enabled)
{
    globalDebugEnabled = enabled;
}

/*!
    Creates the database tables for all registered models.
*/
bool QDjango::createTables()
{
    bool ret = true;
    foreach (const QByteArray &key, globalMetaModels.keys())
        if (!globalMetaModels[key].createTable())
            ret = false;
    return ret;
}

/*!
    Drops the database tables for all registered models.
*/
bool QDjango::dropTables()
{
    bool ret = true;
    foreach (const QByteArray &key, globalMetaModels.keys())
        if (!globalMetaModels[key].dropTable())
            ret = false;
    return ret;
}

/*!
    Returns the QDjangoMetaModel with the given \a name.
 */
QDjangoMetaModel QDjango::metaModel(const char *name)
{
    return globalMetaModels.value(name);
}

QDjangoMetaModel QDjango::registerModel(const QMetaObject *meta)
{
    const QByteArray name = meta->className();
    if (!globalMetaModels.contains(name))
        globalMetaModels.insert(name, QDjangoMetaModel(meta));
    return globalMetaModels[name];
}

/*!
    Returns the empty SQL limit clause.
*/
QString QDjango::noLimitSql()
{
    const QString driverName = QDjango::database().driverName();
    if (driverName == QLatin1String("QSQLITE") ||
        driverName == QLatin1String("QSQLITE2"))
        return QLatin1String(" LIMIT -1");
    else if (driverName == QLatin1String("QMYSQL"))
        // 2^64 - 1, as recommended by the MySQL documentation
        return QLatin1String(" LIMIT 18446744073709551615");
    else
        return QString();
}

<commit_msg>made QDjango::metaModel a little smarter for reverse lookups<commit_after>/*
 * Copyright (C) 2010-2012 Jeremy Lainé
 * Contact: http://code.google.com/p/qdjango/
 *
 * This file is part of the QDjango Library.
 *
 * 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.
 */

#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
#include <QSqlDriver>
#include <QSqlError>
#include <QSqlQuery>
#include <QStringList>
#include <QThread>

#include "QDjango.h"

static const char *connectionPrefix = "_qdjango_";

QMap<QByteArray, QDjangoMetaModel> globalMetaModels = QMap<QByteArray, QDjangoMetaModel>();
static QDjangoDatabase *globalDatabase = 0;
static bool globalDebugEnabled = false;

/// \cond

QDjangoDatabase::QDjangoDatabase(QObject *parent)
    : QObject(parent), connectionId(0)
{
}

void QDjangoDatabase::threadFinished()
{
    QThread *thread = qobject_cast<QThread*>(sender());
    if (!thread)
        return;

    // cleanup database connection for the thread
    QMutexLocker locker(&mutex);
    disconnect(thread, SIGNAL(finished()), this, SLOT(threadFinished()));
    const QString connectionName = copies.value(thread).connectionName();
    copies.remove(thread);
    if (connectionName.startsWith(QLatin1String(connectionPrefix)))
        QSqlDatabase::removeDatabase(connectionName);
}

static void closeDatabase()
{
    delete globalDatabase;
}

static void initDatabase(QSqlDatabase db)
{
    if (db.driverName() == QLatin1String("QSQLITE")) {
        // enable foreign key constraint handling
        QDjangoQuery query(db);
        query.prepare("PRAGMA foreign_keys=on");
        query.exec();
    }
}

QDjangoQuery::QDjangoQuery(QSqlDatabase db)
    : QSqlQuery(db)
{
}

void QDjangoQuery::addBindValue(const QVariant &val, QSql::ParamType paramType)
{
    // this hack is required so that we do not store a mix of local
    // and UTC times
    if (val.type() == QVariant::DateTime)
        QSqlQuery::addBindValue(val.toDateTime().toLocalTime(), paramType);
    else
        QSqlQuery::addBindValue(val, paramType);
}

bool QDjangoQuery::exec()
{
    if (globalDebugEnabled) {
        qDebug() << "SQL query" << lastQuery();
        QMapIterator<QString, QVariant> i(boundValues());
        while (i.hasNext()) {
            i.next();
            qDebug() << "SQL   " << i.key().toLatin1().data() << "="
                     << i.value().toString().toLatin1().data();
        }
    }
    if (!QSqlQuery::exec()) {
        if (globalDebugEnabled)
            qWarning() << "SQL error" << lastError();
        return false;
    }
    return true;
}

bool QDjangoQuery::exec(const QString &query)
{
    if (globalDebugEnabled)
        qDebug() << "SQL query" << query;
    if (!QSqlQuery::exec(query)) {
        if (globalDebugEnabled)
            qWarning() << "SQL error" << lastError();
        return false;
    }
    return true;
}

/// \endcond

/*!
    \mainpage

    QDjango is a simple yet powerful Object Relation Mapper (ORM) built
    on top of the Qt library. Where possible it tries to follow django's
    ORM API, hence its name.

    \sa QDjango
    \sa QDjangoModel
    \sa QDjangoWhere
    \sa QDjangoQuerySet
*/

/*!
    Returns the database used by QDjango.

    If you call this method from any thread but the application's main thread,
    a new connection to the database will be created. The connection will
    automatically be torn down once the thread finishes.

    \sa setDatabase()
*/
QSqlDatabase QDjango::database()
{
    if (!globalDatabase)
        return QSqlDatabase();

    // if we are in the main thread, return reference connection
    QThread *thread = QThread::currentThread();
    if (thread == globalDatabase->thread())
        return globalDatabase->reference;

    // if we have a connection for this thread, return it
    QMutexLocker locker(&globalDatabase->mutex);
    if (globalDatabase->copies.contains(thread))
        return globalDatabase->copies[thread];

    // create a new connection for this thread
    QObject::connect(thread, SIGNAL(finished()), globalDatabase, SLOT(threadFinished()));
    QSqlDatabase db = QSqlDatabase::cloneDatabase(globalDatabase->reference,
        QLatin1String(connectionPrefix) + QString::number(globalDatabase->connectionId++));
    db.open();
    initDatabase(db);
    globalDatabase->copies.insert(thread, db);
    return db;
}

/*!
    Sets the database used by QDjango.

    You must call this method from your application's main thread.

    \sa database()
*/
void QDjango::setDatabase(QSqlDatabase database)
{
    if (database.driverName() != QLatin1String("QSQLITE") &&
        database.driverName() != QLatin1String("QSQLITE2") &&
        database.driverName() != QLatin1String("QMYSQL") &&
        database.driverName() != QLatin1String("QPSQL"))
    {
        qWarning() << "Unsupported database driver" << database.driverName();
    }
    if (!globalDatabase)
    {
        globalDatabase = new QDjangoDatabase();
        qAddPostRoutine(closeDatabase);
    }
    initDatabase(database);
    globalDatabase->reference = database;
}

/*!
    Returns whether debugging information should be printed.

    \sa setDebugEnabled()
*/
bool QDjango::isDebugEnabled()
{
    return globalDebugEnabled;
}

/*!
    Sets whether debugging information should be printed.

    \sa isDebugEnabled()
*/
void QDjango::setDebugEnabled(bool enabled)
{
    globalDebugEnabled = enabled;
}

/*!
    Creates the database tables for all registered models.
*/
bool QDjango::createTables()
{
    bool ret = true;
    foreach (const QByteArray &key, globalMetaModels.keys())
        if (!globalMetaModels[key].createTable())
            ret = false;
    return ret;
}

/*!
    Drops the database tables for all registered models.
*/
bool QDjango::dropTables()
{
    bool ret = true;
    foreach (const QByteArray &key, globalMetaModels.keys())
        if (!globalMetaModels[key].dropTable())
            ret = false;
    return ret;
}

/*!
    Returns the QDjangoMetaModel with the given \a name.
 */
QDjangoMetaModel QDjango::metaModel(const char *name)
{
    if (globalMetaModels.contains(name))
        return globalMetaModels.value(name);

    // otherwise, try to find a model anyway
    foreach (QByteArray modelName, globalMetaModels.keys()) {
        if (qstricmp(name, modelName.data()) == 0)
            return globalMetaModels.value(modelName);
    }

    return QDjangoMetaModel();
}

QDjangoMetaModel QDjango::registerModel(const QMetaObject *meta)
{
    const QByteArray name = meta->className();
    if (!globalMetaModels.contains(name))
        globalMetaModels.insert(name, QDjangoMetaModel(meta));
    return globalMetaModels[name];
}

/*!
    Returns the empty SQL limit clause.
*/
QString QDjango::noLimitSql()
{
    const QString driverName = QDjango::database().driverName();
    if (driverName == QLatin1String("QSQLITE") ||
        driverName == QLatin1String("QSQLITE2"))
        return QLatin1String(" LIMIT -1");
    else if (driverName == QLatin1String("QMYSQL"))
        // 2^64 - 1, as recommended by the MySQL documentation
        return QLatin1String(" LIMIT 18446744073709551615");
    else
        return QString();
}

<|endoftext|>


<commit_before>#include "common.h"

void run_tests(int argc, char** argv) {
    cout << "\n---- BEGIN TEST SUITE ----\n" << endl;
    //test_RANDGAUSS();
    //test_read_program_flags(argc, argv);
    //test_energy_of_water_with_index();
    //test_calculate_energy();
    //test_run_mc();
    //test_radial_dist_sampler();
    //test_write_to_vmd_file(argc, argv);
    //test_write_config_file(argc, argv);
    //test_read_config_file(argc, argv);
    cout << "---- END TEST SUITE ----\n" << endl;
    return;
}

void test_RANDGAUSS() {
    cout << "---- BEGIN TEST - RANDGAUSS ----" << endl;
    double a;
    int bins[20];
    for (int i = 0; i < 20; i++)
        bins[i] = 0;

    for (int i = 0; i < 1000; i++) {
        a = RANDGAUSS(100.0, 0.5);
        for (int j = 0; j < 20; j++) {
            if (j == 19 || (a < 98.0 + j * 0.2)) {
                bins[j]++;
                break;
            }
        }
    }
    for (int i = 0; i < 20; i++)
        cout << bins[i] << endl;

    cout << "---- END TEST - RANDGAUSS ----\n" << endl;
    return;
}

void test_read_program_flags(int argc, char** argv) {
    cout << "---- BEGIN TEST - READ PROGRAM FLAGS ----" << endl;
    read_program_flags(argc, argv);
    NUM_EQUILIBRATION_SWEEPS = 5;
    initialize();
    cout << "---- END TEST - READ PROGRAM FLAGS ----\n" << endl;
    return;
}

void test_energy_of_water_with_index() {
    cout << "---- BEGIN TEST - ENERGY AT SINGLE PARTICLE ----" << endl;
    NUM_WATERS = 2;
    BOX_LENGTH = 10.0;
    water_O_positions = new double*[NUM_WATERS];
    for (int i = 0; i < NUM_WATERS; i++)
        water_O_positions[i] = new double[3];

    water_O_positions[0][0] = 0.0;
    water_O_positions[0][1] = 0.0;
    water_O_positions[0][2] = 0.0;

    water_O_positions[1][0] = 9.0;
    water_O_positions[1][1] = 9.0;
    water_O_positions[1][2] = 9.0;

    for (int i = 0; i < NUM_WATERS; i++)
        cout << "Energy of particle " << setprecision(10) << i << " (kJ):"
            << energy_of_water_with_index(i) << endl;

    cout << "---- END TEST - ENERGY AT SINGLE PARTICLE ----\n" << endl;
    return;
}

void test_calculate_energy() {
    cout << "---- BEGIN TEST - CALCULATE SYSTEM ENERGY ----" << endl;
    NUM_WATERS = 4;
    BOX_LENGTH = 10.0;
    water_O_positions = new double*[NUM_WATERS];
    for (int i = 0; i < NUM_WATERS; i++)
        water_O_positions[i] = new double[3];

    water_O_positions[0][0] = 0.0;
    water_O_positions[0][1] = 0.0;
    water_O_positions[0][2] = 0.0;

    water_O_positions[1][0] = 9.0;
    water_O_positions[1][1] = 9.0;
    water_O_positions[1][2] = 9.0;

    water_O_positions[2][0] = 1.0;
    water_O_positions[2][1] = 2.0;
    water_O_positions[2][2] = 3.0;

    water_O_positions[3][0] = 3.0;
    water_O_positions[3][1] = 1.0;
    water_O_positions[3][2] = 5.0;

    calculate_energy();
    cout << "System Energy: " << setprecision(10) << LJEnergy << endl;
    cout << "---- END TEST - CALCULATE SYSTEM ENERGY ----\n" << endl;
    return;
}

void test_run_mc() {
    cout << "---- BEGIN TEST - MC STEP ----" << endl;
    NUM_WATERS = 4;
    BOX_LENGTH = 10.0;
    water_O_positions = new double*[NUM_WATERS];
    for (int i = 0; i < NUM_WATERS; i++)
        water_O_positions[i] = new double[3];

    water_O_positions[0][0] = 0.0;
    water_O_positions[0][1] = 0.0;
    water_O_positions[0][2] = 0.0;

    water_O_positions[1][0] = 9.0;
    water_O_positions[1][1] = 9.0;
    water_O_positions[1][2] = 9.0;

    water_O_positions[2][0] = 1.0;
    water_O_positions[2][1] = 2.0;
    water_O_positions[2][2] = 3.0;

    water_O_positions[3][0] = 3.0;
    water_O_positions[3][1] = 1.0;
    water_O_positions[3][2] = 5.0;

    calculate_energy();
    for (int k = 0; k < 10000; k++) {
        run_mc();
        cout << "Current system energy: " << setprecision(10) << LJEnergy << endl;
    }
    cout << "---- END TEST - MC STEPPING ----\n" << endl;
    return;
}

void test_radial_dist_sampler() {
    cout << "---- BEGIN TEST - RADIAL DISTRIBUTION SAMPLER ----" << endl;

    initialize();
    run_mc();
    compute_radial_dist_results();

    cout << "\nr(Angstroms)\tg(r)" << endl;
    for (int k = 0; k < radial_dist_num_his_bars; k++)
        cout << setprecision(10) << radial_dist_distance[k] << "\t" << radial_dist_data[k] << endl;

    cout << "\n---- END TEST - RADIAL DISTRIBUTION SAMPLER ----\n" << endl;
    return;
}

void test_write_to_vmd_file(int argc, char** argv) {
    cout << "---- BEGIN TEST - WRITE TO VMD FILE ----" << endl;

    read_program_flags(argc, argv);
    open_vmd_file();
    initialize_constants();
    initialize_waters();
    write_config_to_vmd_file();
    NUM_EQUILIBRATION_SWEEPS = 50;
    mc_equilibrate();
    write_config_to_vmd_file();
    close_vmd_file();

    cout << "---- END TEST - WRITE TO VMD FILE ----\n" << endl;
    return;
}

void test_write_config_file(int argc, char** argv) {
    cout << "---- BEGIN TEST - WRITE CONFIG FILE ----" << endl;

    read_program_flags(argc, argv);
    initialize_constants();
    initialize_waters();
    save_config_to_file();
    cout << "---- END TEST - WRITE CONFIG FILE ----\n" << endl;
    return;

}

void test_read_config_file(int argc, char** argv) {
    cout << "---- BEGIN TEST - READ CONFIG FILE ----" << endl;

    input_config_filename = "sample.config";
    load_configuration_file();
    calculate_energy();
    print_system_vars();
    print_system_config();

    cout << "---- END TEST - READ CONFIG FILE ----\n" << endl;
    return;
}

void print_system_vars() {
    cout << "System temperature (K): " << setprecision(10) << TEMPERATURE << endl
            << "Number of water particles: " << NUM_WATERS << endl
            << "Box length (Angstroms): " << BOX_LENGTH << endl
            << "Water sigma (Angstroms): " << WATER_SIGMA << endl
            << "System energy (kJ): " << LJEnergy << endl << endl
            << "Number of single particle move attempts per MC sweep: " << NUM_MC_ATTEMPTS_PER_SWEEP << endl
            << "Number of MC sweeps: " << NUM_MC_SWEEPS << endl
            << "Number of equilibration sweeps: " << NUM_EQUILIBRATION_SWEEPS << endl << endl;

    if (using_input_config_file)
        cout << "--input (-r) flag raised; using file \'" << input_config_filename << "\'" << endl;
    if (use_custom_output_vmd_filename)
        cout << "--output_vmd (-v) flag raised; will write VMD to \'" << output_vmd_filename << "\'" << endl;
    if (use_custom_output_config_filename)
        cout << "--output_config (-w) flag raised; will save config to \'" << output_config_filename << "\'" << endl;
    cout << endl;
    return;
}

void print_system_config() {
    cout << "Atom configuration:" << endl;
    for (int i = 0; i < NUM_WATERS; i++)
        cout << "Water " << i + 1 << " of " << NUM_WATERS << ": " << setprecision(10)
        << water_O_positions[i][0] << "\t"
            << water_O_positions[i][1] << "\t"
            << water_O_positions[i][2] << endl;
    return;
}
<commit_msg>preparing VMD output<commit_after>#include "common.h"

void run_tests(int argc, char** argv) {
    cout << "\n---- BEGIN TEST SUITE ----\n" << endl;
    //test_RANDGAUSS();
    //test_read_program_flags(argc, argv);
    //test_energy_of_water_with_index();
    //test_calculate_energy();
    //test_run_mc();
    //test_radial_dist_sampler();
    //test_write_to_vmd_file(argc, argv);
    //test_write_config_file(argc, argv);
    //test_read_config_file(argc, argv);
    cout << "---- END TEST SUITE ----\n" << endl;
    return;
}

void test_RANDGAUSS() {
    cout << "---- BEGIN TEST - RANDGAUSS ----" << endl;
    double a;
    int bins[20];
    for (int i = 0; i < 20; i++)
        bins[i] = 0;

    for (int i = 0; i < 1000; i++) {
        a = RANDGAUSS(100.0, 0.5);
        for (int j = 0; j < 20; j++) {
            if (j == 19 || (a < 98.0 + j * 0.2)) {
                bins[j]++;
                break;
            }
        }
    }
    for (int i = 0; i < 20; i++)
        cout << bins[i] << endl;

    cout << "---- END TEST - RANDGAUSS ----\n" << endl;
    return;
}

void test_read_program_flags(int argc, char** argv) {
    cout << "---- BEGIN TEST - READ PROGRAM FLAGS ----" << endl;
    read_program_flags(argc, argv);
    NUM_EQUILIBRATION_SWEEPS = 5;
    initialize();
    cout << "---- END TEST - READ PROGRAM FLAGS ----\n" << endl;
    return;
}

void test_energy_of_water_with_index() {
    cout << "---- BEGIN TEST - ENERGY AT SINGLE PARTICLE ----" << endl;
    NUM_WATERS = 2;
    BOX_LENGTH = 10.0;
    water_O_positions = new double*[NUM_WATERS];
    for (int i = 0; i < NUM_WATERS; i++)
        water_O_positions[i] = new double[3];

    water_O_positions[0][0] = 0.0;
    water_O_positions[0][1] = 0.0;
    water_O_positions[0][2] = 0.0;

    water_O_positions[1][0] = 9.0;
    water_O_positions[1][1] = 9.0;
    water_O_positions[1][2] = 9.0;

    for (int i = 0; i < NUM_WATERS; i++)
        cout << "Energy of particle " << setprecision(10) << i << " (kJ):"
            << energy_of_water_with_index(i) << endl;

    cout << "---- END TEST - ENERGY AT SINGLE PARTICLE ----\n" << endl;
    return;
}

void test_calculate_energy() {
    cout << "---- BEGIN TEST - CALCULATE SYSTEM ENERGY ----" << endl;
    NUM_WATERS = 4;
    BOX_LENGTH = 10.0;
    water_O_positions = new double*[NUM_WATERS];
    for (int i = 0; i < NUM_WATERS; i++)
        water_O_positions[i] = new double[3];

    water_O_positions[0][0] = 0.0;
    water_O_positions[0][1] = 0.0;
    water_O_positions[0][2] = 0.0;

    water_O_positions[1][0] = 9.0;
    water_O_positions[1][1] = 9.0;
    water_O_positions[1][2] = 9.0;

    water_O_positions[2][0] = 1.0;
    water_O_positions[2][1] = 2.0;
    water_O_positions[2][2] = 3.0;

    water_O_positions[3][0] = 3.0;
    water_O_positions[3][1] = 1.0;
    water_O_positions[3][2] = 5.0;

    calculate_energy();
    cout << "System Energy: " << setprecision(10) << LJEnergy << endl;
    cout << "---- END TEST - CALCULATE SYSTEM ENERGY ----\n" << endl;
    return;
}

void test_run_mc() {
    cout << "---- BEGIN TEST - MC STEP ----" << endl;
    NUM_WATERS = 4;
    BOX_LENGTH = 10.0;
    water_O_positions = new double*[NUM_WATERS];
    for (int i = 0; i < NUM_WATERS; i++)
        water_O_positions[i] = new double[3];

    water_O_positions[0][0] = 0.0;
    water_O_positions[0][1] = 0.0;
    water_O_positions[0][2] = 0.0;

    water_O_positions[1][0] = 9.0;
    water_O_positions[1][1] = 9.0;
    water_O_positions[1][2] = 9.0;

    water_O_positions[2][0] = 1.0;
    water_O_positions[2][1] = 2.0;
    water_O_positions[2][2] = 3.0;

    water_O_positions[3][0] = 3.0;
    water_O_positions[3][1] = 1.0;
    water_O_positions[3][2] = 5.0;

    calculate_energy();
    for (int k = 0; k < 10000; k++) {
        run_mc();
        cout << "Current system energy: " << setprecision(10) << LJEnergy << endl;
    }
    cout << "---- END TEST - MC STEPPING ----\n" << endl;
    return;
}

void test_radial_dist_sampler() {
    cout << "---- BEGIN TEST - RADIAL DISTRIBUTION SAMPLER ----" << endl;

    initialize();
    run_mc();
    compute_radial_dist_results();

    cout << "\nr(Angstroms)\tg(r)" << endl;
    for (int k = 0; k < radial_dist_num_his_bars; k++)
        cout << setprecision(10) << radial_dist_distance[k] << "\t" << radial_dist_data[k] << endl;

    cout << "\n---- END TEST - RADIAL DISTRIBUTION SAMPLER ----\n" << endl;
    return;
}

void test_write_to_vmd_file(int argc, char** argv) {
    cout << "---- BEGIN TEST - WRITE TO VMD FILE ----" << endl;

    read_program_flags(argc, argv);
    open_vmd_file();
    initialize_constants();
    initialize_waters();
    write_config_to_vmd_file();
    NUM_EQUILIBRATION_SWEEPS = 50;
    for (int g = 0; g < 10; g++) {
        mc_equilibrate();
        write_config_to_vmd_file();
    }
    close_vmd_file();

    cout << "---- END TEST - WRITE TO VMD FILE ----\n" << endl;
    return;
}

void test_write_config_file(int argc, char** argv) {
    cout << "---- BEGIN TEST - WRITE CONFIG FILE ----" << endl;

    read_program_flags(argc, argv);
    initialize_constants();
    initialize_waters();
    save_config_to_file();
    cout << "---- END TEST - WRITE CONFIG FILE ----\n" << endl;
    return;

}

void test_read_config_file(int argc, char** argv) {
    cout << "---- BEGIN TEST - READ CONFIG FILE ----" << endl;

    input_config_filename = "sample.config";
    load_configuration_file();
    calculate_energy();
    print_system_vars();
    print_system_config();

    cout << "---- END TEST - READ CONFIG FILE ----\n" << endl;
    return;
}

void print_system_vars() {
    cout << "System temperature (K): " << setprecision(10) << TEMPERATURE << endl
            << "Number of water particles: " << NUM_WATERS << endl
            << "Box length (Angstroms): " << BOX_LENGTH << endl
            << "Water sigma (Angstroms): " << WATER_SIGMA << endl
            << "System energy (kJ): " << LJEnergy << endl << endl
            << "Number of single particle move attempts per MC sweep: " << NUM_MC_ATTEMPTS_PER_SWEEP << endl
            << "Number of MC sweeps: " << NUM_MC_SWEEPS << endl
            << "Number of equilibration sweeps: " << NUM_EQUILIBRATION_SWEEPS << endl << endl;

    if (using_input_config_file)
        cout << "--input (-r) flag raised; using file \'" << input_config_filename << "\'" << endl;
    if (use_custom_output_vmd_filename)
        cout << "--output_vmd (-v) flag raised; will write VMD to \'" << output_vmd_filename << "\'" << endl;
    if (use_custom_output_config_filename)
        cout << "--output_config (-w) flag raised; will save config to \'" << output_config_filename << "\'" << endl;
    cout << endl;
    return;
}

void print_system_config() {
    cout << "Atom configuration:" << endl;
    for (int i = 0; i < NUM_WATERS; i++)
        cout << "Water " << i + 1 << " of " << NUM_WATERS << ": " << setprecision(10)
        << water_O_positions[i][0] << "\t"
            << water_O_positions[i][1] << "\t"
            << water_O_positions[i][2] << endl;
    return;
}
<|endoftext|>


<commit_before>/// \file urbi/uvalue.hxx

// This file is part of UObject Component Architecture
// Copyright (c) 2009 Gostai S.A.S.
//
// Permission to use, copy, modify, and redistribute this software for
// non-commercial use is hereby granted.
//
// This software is provided "as is" without warranty of any kind,
// either expressed or implied, including but not limited to the
// implied warranties of fitness for a particular purpose.
//
// For more information, comments, bug reports: http://www.urbiforge.com

#ifndef URBI_UVALUE_HXX
# define URBI_UVALUE_HXX

# include <cassert>
# include <urbi/uvalue.hh>
# include <libport/assert.hh>

namespace urbi
{

  /*--------.
  | UList.  |
  `--------*/

# define ULIST_NTH(Const)                       \
  inline                                        \
  Const UValue&                                 \
  UList::operator[](size_t i) Const             \
  {                                             \
    i += offset;                                \
    if (i < size())                             \
      return *array[i];                         \
    else                                        \
      return UValue::error();                   \
  }

  ULIST_NTH(const)
  ULIST_NTH(/* const */)

# undef ULIST_NTH

  inline
  size_t
  UList::size() const
  {
    return array.size();
  }

  inline
  void
  UList::setOffset(size_t n)
  {
    offset = n;
  }

  /*--------------.
  | UNamedValue.  |
  `--------------*/

  inline
  UNamedValue::UNamedValue(const std::string& n, UValue* v)
    : name(n)
    , val(v)
  {}

  inline
  UNamedValue&
  UNamedValue::error()
  {
    static UNamedValue instance("<<UNamedValue::error (denotes an error)>>");
    return instance;
  }

  /*----------------.
  | UObjectStruct.  |
  `----------------*/

# define UOBJECTSTRUCT_NTH(Const)               \
  inline                                        \
  Const UNamedValue&                            \
  UObjectStruct::operator[](size_t i) Const     \
  {                                             \
    if (i < size())                             \
      return array[i];                          \
    else                                        \
      return UNamedValue::error();              \
  }

  UOBJECTSTRUCT_NTH(const)
  UOBJECTSTRUCT_NTH(/* const */)

# undef UOBJECTSTRUCT_NTH

  inline
  size_t
  UObjectStruct::size() const
  {
    return array.size();
  }

  /*---------.
  | UValue.  |
  `---------*/

  /// We use an operator , that behaves like an assignment.  The
  /// only difference is when the rhs is void, in which case it is
  /// the regular comma which is used.  This allows to write "uval,
  /// expr" to mean "compute expr and assign its result to uval,
  /// unless expr is void".
  inline
  UValue&
  UValue::operator, (const UValue &b)
  {
    return *this = b;
  }

#  define CONTAINER_TO_UVALUE_DECLARE(Type)                     \
  template <typename T>                                         \
  inline                                                        \
  UValue&                                                       \
  operator, (UValue &b, const Type<T> &v)                       \
  {                                                             \
    b.type = DATA_LIST;                                         \
    b.list = new UList();                                       \
    for (typename Type<T>::const_iterator i = v.begin(),        \
           i_end = v.end();                                     \
         i != i_end; ++i)                                       \
    {                                                           \
      UValue r;                                                 \
      r, *i;                                                    \
      b.list->array.push_back(new UValue(r));                   \
    }                                                           \
    return b;                                                   \
  }

  CONTAINER_TO_UVALUE_DECLARE(std::list)
  CONTAINER_TO_UVALUE_DECLARE(std::vector)

# undef CONTAINER_TO_UVALUE_DECLARE

#define CTOR_AND_ASSIGN_AND_COMMA(Type)		\
  inline                                        \
  UValue& UValue::operator, (Type rhs)          \
  {						\
    return *this = rhs;                         \
  }

  // UFloats.
  CTOR_AND_ASSIGN_AND_COMMA(ufloat);
  CTOR_AND_ASSIGN_AND_COMMA(int);
  CTOR_AND_ASSIGN_AND_COMMA(long);
  CTOR_AND_ASSIGN_AND_COMMA(unsigned int);
  CTOR_AND_ASSIGN_AND_COMMA(unsigned long);

  // Strings.
  CTOR_AND_ASSIGN_AND_COMMA(const char*);
  CTOR_AND_ASSIGN_AND_COMMA(const void*);
  CTOR_AND_ASSIGN_AND_COMMA(const std::string&);

  // Others.
  CTOR_AND_ASSIGN_AND_COMMA(const UBinary&);
  CTOR_AND_ASSIGN_AND_COMMA(const UList&);
  CTOR_AND_ASSIGN_AND_COMMA(const UObjectStruct&);
  CTOR_AND_ASSIGN_AND_COMMA(const USound&);
  CTOR_AND_ASSIGN_AND_COMMA(const UImage&);

#undef CTOR_AND_ASSIGN_AND_COMMA

#define UVALUE_INTEGRAL_CAST(Type)                              \
  inline                                                        \
  UValue::operator Type() const                                 \
  {                                                             \
    return static_cast<Type>(static_cast<ufloat>((*this)));     \
  }

  UVALUE_INTEGRAL_CAST(int)
  UVALUE_INTEGRAL_CAST(unsigned int)
  UVALUE_INTEGRAL_CAST(long)
  UVALUE_INTEGRAL_CAST(unsigned long)
#undef UVALUE_INTEGRAL_CAST

  inline
  UValue::operator bool() const
  {
    return static_cast<int>(static_cast<ufloat>((*this))) != 0;
  }

  inline
  UValue&
  UValue::operator()()
  {
    return *this;
  }

  inline
  std::ostream&
  operator<<(std::ostream& s, const UValue& v)
  {
    // Looks bizarre, but might happen without have the "print" die
    // (it *has* happened).
    assert(&v);
    return v.print(s);
  }

  /*----------.
  | Casters.  |
  `----------*/

  // Run the uvalue_caster<Type> on v.
  template <typename Type>
  typename uvar_ref_traits<typename libport::unref_traits<Type>::type>::type
  uvalue_cast(UValue& v)
  {
    return uvalue_caster<typename libport::unref_traits<Type>::type>()(v);
  }

# define UVALUE_CASTER_DEFINE(Type)		\
  template <>					\
  struct uvalue_caster <Type>			\
  {						\
    Type operator() (UValue& v)			\
    {						\
      return v;					\
    }						\
  };

  UVALUE_CASTER_DEFINE(int);
  UVALUE_CASTER_DEFINE(unsigned int);
  UVALUE_CASTER_DEFINE(long);
  UVALUE_CASTER_DEFINE(unsigned long);
  UVALUE_CASTER_DEFINE(ufloat);
  UVALUE_CASTER_DEFINE(std::string);
  UVALUE_CASTER_DEFINE(const std::string);
  UVALUE_CASTER_DEFINE(bool);
  UVALUE_CASTER_DEFINE(UImage);
  UVALUE_CASTER_DEFINE(USound);

#undef UVALUE_CASTER_DEFINE

  template <>
  struct uvalue_caster<const UValue&>
  {
    const UValue& operator()(UValue& v)
      {
        return v;
      }
  };

  template <>
  struct uvalue_caster<UValue&>
  {
    UValue& operator()(UValue& v)
      {
        return v;
      }
  };

  template <>
  struct uvalue_caster<UValue>
  {
    UValue operator()(UValue& v)
      {
        return v;
      }
  };

  template <>
  struct uvalue_caster<const UValue>
  {
    const UValue operator()(UValue& v)
      {
        return v;
      }
  };

  // The following ones are defined in uvalue-common.cc.
  template <>
  struct URBI_SDK_API uvalue_caster<UVar>
  {
    UVar& operator () (UValue& v);
  };

# define UVALUE_CASTER_DECLARE(Type)		\
  template <>					\
  struct URBI_SDK_API uvalue_caster<Type>       \
  {                                             \
    Type operator () (UValue& v);		\
  }

  UVALUE_CASTER_DECLARE(UBinary);
  UVALUE_CASTER_DECLARE(UList);
  UVALUE_CASTER_DECLARE(UObjectStruct);
  UVALUE_CASTER_DECLARE(const char*);

# undef UVALUE_CASTER_DECLARE

# ifndef UOBJECT_NO_LIST_CAST

#  define UVALUE_CONTAINER_CASTER_DECLARE(Type)                 \
  template <typename T>                                         \
  struct uvalue_caster< Type<T> >                               \
  {                                                             \
    Type<T>                                                     \
    operator()(UValue& v)                                       \
    {                                                           \
      Type<T> res;                                              \
      if (v.type != DATA_LIST)                                  \
        /* Cast just the element.  */                           \
        res.push_back(uvalue_cast<T>(v));                       \
      else                                                      \
        for (size_t i = 0; i < v.list->size(); ++i)             \
          res.push_back(uvalue_cast<T>(*v.list->array[i]));     \
      return res;                                               \
    }                                                           \
  }

  UVALUE_CONTAINER_CASTER_DECLARE(std::list);
  UVALUE_CONTAINER_CASTER_DECLARE(std::vector);

#  undef UVALUE_CONTAINER_CASTER_DECLARE

# endif

} // namespace urbi

#endif // ! URBI_UVALUE_HXX
<commit_msg>uvalue: factoring.<commit_after>/// \file urbi/uvalue.hxx

// This file is part of UObject Component Architecture
// Copyright (c) 2009 Gostai S.A.S.
//
// Permission to use, copy, modify, and redistribute this software for
// non-commercial use is hereby granted.
//
// This software is provided "as is" without warranty of any kind,
// either expressed or implied, including but not limited to the
// implied warranties of fitness for a particular purpose.
//
// For more information, comments, bug reports: http://www.urbiforge.com

#ifndef URBI_UVALUE_HXX
# define URBI_UVALUE_HXX

# include <cassert>
# include <urbi/uvalue.hh>
# include <libport/assert.hh>

namespace urbi
{

  /*--------.
  | UList.  |
  `--------*/

# define ULIST_NTH(Const)                       \
  inline                                        \
  Const UValue&                                 \
  UList::operator[](size_t i) Const             \
  {                                             \
    i += offset;                                \
    if (i < size())                             \
      return *array[i];                         \
    else                                        \
      return UValue::error();                   \
  }

  ULIST_NTH(const)
  ULIST_NTH(/* const */)

# undef ULIST_NTH

  inline
  size_t
  UList::size() const
  {
    return array.size();
  }

  inline
  void
  UList::setOffset(size_t n)
  {
    offset = n;
  }

  /*--------------.
  | UNamedValue.  |
  `--------------*/

  inline
  UNamedValue::UNamedValue(const std::string& n, UValue* v)
    : name(n)
    , val(v)
  {}

  inline
  UNamedValue&
  UNamedValue::error()
  {
    static UNamedValue instance("<<UNamedValue::error (denotes an error)>>");
    return instance;
  }

  /*----------------.
  | UObjectStruct.  |
  `----------------*/

# define UOBJECTSTRUCT_NTH(Const)               \
  inline                                        \
  Const UNamedValue&                            \
  UObjectStruct::operator[](size_t i) Const     \
  {                                             \
    if (i < size())                             \
      return array[i];                          \
    else                                        \
      return UNamedValue::error();              \
  }

  UOBJECTSTRUCT_NTH(const)
  UOBJECTSTRUCT_NTH(/* const */)

# undef UOBJECTSTRUCT_NTH

  inline
  size_t
  UObjectStruct::size() const
  {
    return array.size();
  }

  /*---------.
  | UValue.  |
  `---------*/

  /// We use an operator , that behaves like an assignment.  The
  /// only difference is when the rhs is void, in which case it is
  /// the regular comma which is used.  This allows to write "uval,
  /// expr" to mean "compute expr and assign its result to uval,
  /// unless expr is void".
  inline
  UValue&
  UValue::operator, (const UValue &b)
  {
    return *this = b;
  }

#  define CONTAINER_TO_UVALUE_DECLARE(Type)                     \
  template <typename T>                                         \
  inline                                                        \
  UValue&                                                       \
  operator, (UValue &b, const Type<T> &v)                       \
  {                                                             \
    b.type = DATA_LIST;                                         \
    b.list = new UList();                                       \
    for (typename Type<T>::const_iterator i = v.begin(),        \
           i_end = v.end();                                     \
         i != i_end; ++i)                                       \
    {                                                           \
      UValue r;                                                 \
      r, *i;                                                    \
      b.list->array.push_back(new UValue(r));                   \
    }                                                           \
    return b;                                                   \
  }

  CONTAINER_TO_UVALUE_DECLARE(std::list)
  CONTAINER_TO_UVALUE_DECLARE(std::vector)

# undef CONTAINER_TO_UVALUE_DECLARE

# define CTOR_AND_ASSIGN_AND_COMMA(Type)        \
  inline                                        \
  UValue& UValue::operator, (Type rhs)          \
  {						\
    return *this = rhs;                         \
  }

  // UFloats.
  CTOR_AND_ASSIGN_AND_COMMA(ufloat);
  CTOR_AND_ASSIGN_AND_COMMA(int);
  CTOR_AND_ASSIGN_AND_COMMA(long);
  CTOR_AND_ASSIGN_AND_COMMA(unsigned int);
  CTOR_AND_ASSIGN_AND_COMMA(unsigned long);

  // Strings.
  CTOR_AND_ASSIGN_AND_COMMA(const char*);
  CTOR_AND_ASSIGN_AND_COMMA(const void*);
  CTOR_AND_ASSIGN_AND_COMMA(const std::string&);

  // Others.
  CTOR_AND_ASSIGN_AND_COMMA(const UBinary&);
  CTOR_AND_ASSIGN_AND_COMMA(const UList&);
  CTOR_AND_ASSIGN_AND_COMMA(const UObjectStruct&);
  CTOR_AND_ASSIGN_AND_COMMA(const USound&);
  CTOR_AND_ASSIGN_AND_COMMA(const UImage&);

# undef CTOR_AND_ASSIGN_AND_COMMA

# define UVALUE_INTEGRAL_CAST(Type)                             \
  inline                                                        \
  UValue::operator Type() const                                 \
  {                                                             \
    return static_cast<Type>(static_cast<ufloat>((*this)));     \
  }

  UVALUE_INTEGRAL_CAST(int)
  UVALUE_INTEGRAL_CAST(unsigned int)
  UVALUE_INTEGRAL_CAST(long)
  UVALUE_INTEGRAL_CAST(unsigned long)
# undef UVALUE_INTEGRAL_CAST

  inline
  UValue::operator bool() const
  {
    return static_cast<int>(static_cast<ufloat>((*this))) != 0;
  }

  inline
  UValue&
  UValue::operator()()
  {
    return *this;
  }

  inline
  std::ostream&
  operator<<(std::ostream& s, const UValue& v)
  {
    // Looks bizarre, but might happen without have the "print" die
    // (it *has* happened).
    assert(&v);
    return v.print(s);
  }

  /*----------.
  | Casters.  |
  `----------*/

  // Run the uvalue_caster<Type> on v.
  template <typename Type>
  typename uvar_ref_traits<typename libport::unref_traits<Type>::type>::type
  uvalue_cast(UValue& v)
  {
    return uvalue_caster<typename libport::unref_traits<Type>::type>()(v);
  }

# define UVALUE_CASTER_DEFINE(Type)		\
  template <>					\
  struct uvalue_caster <Type>			\
  {						\
    Type operator() (UValue& v)			\
    {						\
      return v;					\
    }						\
  };

  UVALUE_CASTER_DEFINE(int);
  UVALUE_CASTER_DEFINE(unsigned int);
  UVALUE_CASTER_DEFINE(long);
  UVALUE_CASTER_DEFINE(unsigned long);
  UVALUE_CASTER_DEFINE(ufloat);
  UVALUE_CASTER_DEFINE(std::string);
  UVALUE_CASTER_DEFINE(const std::string);
  UVALUE_CASTER_DEFINE(bool);
  UVALUE_CASTER_DEFINE(UImage);
  UVALUE_CASTER_DEFINE(USound);

#undef UVALUE_CASTER_DEFINE

  /*-----------------------------------.
  | Casting an UValue into an UValue.  |
  `-----------------------------------*/

# define UVALUE_CASTER_DEFINE(Type)              \
  template <>                                   \
  struct uvalue_caster<Type>                    \
  {                                             \
    Type operator()(UValue& v)                  \
    {                                           \
      return v;                                 \
    }                                           \
  }

  UVALUE_CASTER_DEFINE(const UValue&);
  UVALUE_CASTER_DEFINE(UValue&);
  UVALUE_CASTER_DEFINE(const UValue);
  UVALUE_CASTER_DEFINE(UValue);
# undef UVALUE_CASTER_DEFINE

  // The following ones are defined in uvalue-common.cc.
  template <>
  struct URBI_SDK_API uvalue_caster<UVar>
  {
    UVar& operator () (UValue& v);
  };

# define UVALUE_CASTER_DECLARE(Type)		\
  template <>					\
  struct URBI_SDK_API uvalue_caster<Type>       \
  {                                             \
    Type operator () (UValue& v);		\
  }

  UVALUE_CASTER_DECLARE(UBinary);
  UVALUE_CASTER_DECLARE(UList);
  UVALUE_CASTER_DECLARE(UObjectStruct);
  UVALUE_CASTER_DECLARE(const char*);

# undef UVALUE_CASTER_DECLARE

# ifndef UOBJECT_NO_LIST_CAST

#  define UVALUE_CONTAINER_CASTER_DECLARE(Type)                 \
  template <typename T>                                         \
  struct uvalue_caster< Type<T> >                               \
  {                                                             \
    Type<T>                                                     \
    operator()(UValue& v)                                       \
    {                                                           \
      Type<T> res;                                              \
      if (v.type != DATA_LIST)                                  \
        /* Cast just the element.  */                           \
        res.push_back(uvalue_cast<T>(v));                       \
      else                                                      \
        for (size_t i = 0; i < v.list->size(); ++i)             \
          res.push_back(uvalue_cast<T>(*v.list->array[i]));     \
      return res;                                               \
    }                                                           \
  }

  UVALUE_CONTAINER_CASTER_DECLARE(std::list);
  UVALUE_CONTAINER_CASTER_DECLARE(std::vector);

#  undef UVALUE_CONTAINER_CASTER_DECLARE

# endif

} // namespace urbi

#endif // ! URBI_UVALUE_HXX
<|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2013 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "joynr/Util.h"
#include <vector>
#include <tuple>
#include <functional>
#include <string>
#include "joynr/types/TestTypes/TEverythingStruct.h"

using namespace joynr;

class UtilTest : public ::testing::Test {
protected:

    struct ExpandTuple {
        bool expandIntoThis(int arg1, float arg2, std::string arg3) {
            return arg1 == 23 && arg2 == 24.25 && arg3 == "Test";
        }
    };

    ExpandTuple expandTuple;
};

TEST_F(UtilTest, splitIntoJsonObjects)
{
    std::string inputStream;
    std::vector<std::string> result;

    inputStream = R"( not a valid Json )";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(0, result.size());

    inputStream = R"({"id":34})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(1, result.size());
    EXPECT_EQ(result.at(0), R"({"id":34})");

    inputStream = R"({"message":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"message":{one:two}})");
    EXPECT_EQ(result.at(1), R"({"id":35})");

    //payload may not contain { or } outside a string.
    inputStream = R"({"id":3{4})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(0, result.size());

    //  { within a string should be ok
    inputStream = R"({"messa{ge":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"messa{ge":{one:two}})");

    //  } within a string should be ok
    inputStream = R"({"messa}ge":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"messa}ge":{one:two}})");

    //  }{ within a string should be ok
    inputStream = R"({"messa}{ge":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"messa}{ge":{one:two}})");

    //  {} within a string should be ok
    inputStream = R"({"messa{}ge":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"messa{}ge":{one:two}})");

    //string may contain \"
    inputStream = R"({"mes\"sa{ge":{one:two}}{"id":35})";
    //inputStream:{"mes\"sa{ge":{one:two}}{"id":35}
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"mes\"sa{ge":{one:two}})");

    inputStream = R"({"mes\\"sa{ge":{one:two}}{"id":35})";
    // inputStream: {"mes\\"sa{ge":{one:two}}{"id":35}
    // / does not escape within JSON String, so the string should not be ended after mes\"
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"mes\\"sa{ge":{one:two}})");
}

TEST_F(UtilTest, convertVectorToVariantVector){

    std::vector<int> intVector;
    std::vector<Variant> variantVector;

    intVector.push_back(2);
    intVector.push_back(5);
    intVector.push_back(-1);

    variantVector.push_back(Variant::make<int>(2));
    variantVector.push_back(Variant::make<int>(5));
    variantVector.push_back(Variant::make<int>(-1));

    std::vector<Variant> convertedVariantVector = util::convertVectorToVariantVector<int>(intVector);
    std::vector<int> convertedIntVector = util::convertVariantVectorToVector<int>(variantVector);

    EXPECT_EQ(convertedVariantVector, variantVector);
    EXPECT_EQ(convertedIntVector, intVector);

    std::vector<Variant> reconvertedVariantVector = util::convertVectorToVariantVector<int>(convertedIntVector);
    std::vector<int> reconvertedIntVector = util::convertVariantVectorToVector<int>(convertedVariantVector);

    EXPECT_EQ(reconvertedVariantVector, variantVector);
    EXPECT_EQ(reconvertedIntVector, intVector);

}

TEST_F(UtilTest, typeIdSingleType) {
    EXPECT_EQ(0, util::getTypeId<void>());
    EXPECT_GT(util::getTypeId<std::string>(), 0);
    EXPECT_NE(util::getTypeId<std::string>(), util::getTypeId<std::int32_t>());
}

TEST_F(UtilTest, typeIdCompositeType){
    int typeId1 = util::getTypeId<std::string, std::int32_t, float>();
    EXPECT_GT(typeId1, 0);

    int typeId2 = util::getTypeId<std::int32_t, std::string, float>();
    EXPECT_NE(typeId1, typeId2);
    int typeIdTEverythingStruct = util::getTypeId<joynr::types::TestTypes::TEverythingStruct>();
    EXPECT_GT(typeIdTEverythingStruct, 0);
    EXPECT_NE(typeId1, typeIdTEverythingStruct);
    EXPECT_NE(typeId2, typeIdTEverythingStruct);
}

TEST_F(UtilTest, typeIdVector){
    int typeIdVectorOfInt = util::getTypeId<std::vector<std::int32_t>>();
    EXPECT_NE(typeIdVectorOfInt, 0);

    int typeIdVectorOfTEverythingStruct = util::getTypeId<std::vector<joynr::types::TestTypes::TEverythingStruct>>();
    EXPECT_NE(typeIdVectorOfTEverythingStruct, 0);
    EXPECT_NE(typeIdVectorOfInt, typeIdVectorOfTEverythingStruct);
}

TEST_F(UtilTest, valueOfFloatVector){
    std::vector<float> expectedFloatVector = {1.1f, 1.2f, 1.3f};

    std::vector<Variant> variantVector;
    for(std::size_t i = 0; i<expectedFloatVector.size(); i++){
        variantVector.push_back(Variant::NULL_VARIANT());
    }
    std::transform(
                expectedFloatVector.cbegin(),
                expectedFloatVector.cend(),
                variantVector.begin(),
                [](const float value) { return Variant::make<double>(value); }
    );
    std::vector<float> floatVector = util::valueOf<std::vector<float>>(Variant::make<std::vector<Variant>>(variantVector));
    for(std::size_t i = 0; i < expectedFloatVector.size(); i++) {
        EXPECT_EQ(expectedFloatVector[i], floatVector[i]);
    }
}
<commit_msg>[C++] cleaned up UtilTest<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2013 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include <vector>
#include <tuple>
#include <functional>
#include <string>

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

#include "joynr/Util.h"
#include "joynr/types/TestTypes/TEverythingStruct.h"

using namespace joynr;

TEST(UtilTest, splitIntoJsonObjects)
{
    std::string inputStream;
    std::vector<std::string> result;

    inputStream = R"( not a valid Json )";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(0, result.size());

    inputStream = R"({"id":34})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(1, result.size());
    EXPECT_EQ(result.at(0), R"({"id":34})");

    inputStream = R"({"message":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"message":{one:two}})");
    EXPECT_EQ(result.at(1), R"({"id":35})");

    //payload may not contain { or } outside a string.
    inputStream = R"({"id":3{4})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(0, result.size());

    //  { within a string should be ok
    inputStream = R"({"messa{ge":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"messa{ge":{one:two}})");

    //  } within a string should be ok
    inputStream = R"({"messa}ge":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"messa}ge":{one:two}})");

    //  }{ within a string should be ok
    inputStream = R"({"messa}{ge":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"messa}{ge":{one:two}})");

    //  {} within a string should be ok
    inputStream = R"({"messa{}ge":{one:two}}{"id":35})";
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"messa{}ge":{one:two}})");

    //string may contain \"
    inputStream = R"({"mes\"sa{ge":{one:two}}{"id":35})";
    //inputStream:{"mes\"sa{ge":{one:two}}{"id":35}
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"mes\"sa{ge":{one:two}})");

    inputStream = R"({"mes\\"sa{ge":{one:two}}{"id":35})";
    // inputStream: {"mes\\"sa{ge":{one:two}}{"id":35}
    // / does not escape within JSON String, so the string should not be ended after mes\"
    result = util::splitIntoJsonObjects(inputStream);
    EXPECT_EQ(2, result.size());
    EXPECT_EQ(result.at(0), R"({"mes\\"sa{ge":{one:two}})");
}

TEST(UtilTest, convertVectorToVariantVector){

    std::vector<int> intVector;
    std::vector<Variant> variantVector;

    intVector.push_back(2);
    intVector.push_back(5);
    intVector.push_back(-1);

    variantVector.push_back(Variant::make<int>(2));
    variantVector.push_back(Variant::make<int>(5));
    variantVector.push_back(Variant::make<int>(-1));

    std::vector<Variant> convertedVariantVector = util::convertVectorToVariantVector<int>(intVector);
    std::vector<int> convertedIntVector = util::convertVariantVectorToVector<int>(variantVector);

    EXPECT_EQ(convertedVariantVector, variantVector);
    EXPECT_EQ(convertedIntVector, intVector);

    std::vector<Variant> reconvertedVariantVector = util::convertVectorToVariantVector<int>(convertedIntVector);
    std::vector<int> reconvertedIntVector = util::convertVariantVectorToVector<int>(convertedVariantVector);

    EXPECT_EQ(reconvertedVariantVector, variantVector);
    EXPECT_EQ(reconvertedIntVector, intVector);

}

TEST(UtilTest, typeIdSingleType) {
    EXPECT_EQ(0, util::getTypeId<void>());
    EXPECT_GT(util::getTypeId<std::string>(), 0);
    EXPECT_NE(util::getTypeId<std::string>(), util::getTypeId<std::int32_t>());
}

TEST(UtilTest, typeIdCompositeType){
    int typeId1 = util::getTypeId<std::string, std::int32_t, float>();
    EXPECT_GT(typeId1, 0);

    int typeId2 = util::getTypeId<std::int32_t, std::string, float>();
    EXPECT_NE(typeId1, typeId2);
    int typeIdTEverythingStruct = util::getTypeId<joynr::types::TestTypes::TEverythingStruct>();
    EXPECT_GT(typeIdTEverythingStruct, 0);
    EXPECT_NE(typeId1, typeIdTEverythingStruct);
    EXPECT_NE(typeId2, typeIdTEverythingStruct);
}

TEST(UtilTest, typeIdVector){
    int typeIdVectorOfInt = util::getTypeId<std::vector<std::int32_t>>();
    EXPECT_NE(typeIdVectorOfInt, 0);

    int typeIdVectorOfTEverythingStruct = util::getTypeId<std::vector<joynr::types::TestTypes::TEverythingStruct>>();
    EXPECT_NE(typeIdVectorOfTEverythingStruct, 0);
    EXPECT_NE(typeIdVectorOfInt, typeIdVectorOfTEverythingStruct);
}

TEST(UtilTest, valueOfFloatVector){
    std::vector<float> expectedFloatVector = {1.1f, 1.2f, 1.3f};

    std::vector<Variant> variantVector;
    for(std::size_t i = 0; i<expectedFloatVector.size(); i++){
        variantVector.push_back(Variant::NULL_VARIANT());
    }
    std::transform(
                expectedFloatVector.cbegin(),
                expectedFloatVector.cend(),
                variantVector.begin(),
                [](const float value) { return Variant::make<double>(value); }
    );
    std::vector<float> floatVector = util::valueOf<std::vector<float>>(Variant::make<std::vector<Variant>>(variantVector));
    for(std::size_t i = 0; i < expectedFloatVector.size(); i++) {
        EXPECT_EQ(expectedFloatVector[i], floatVector[i]);
    }
}
<|endoftext|>