<commit_before>// Copyright (c) 2011-2017 The Bitcoin developers
// Copyright (c) 2015-2021 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "qt/rpcexecutor.h"

#include "rpc/client.h"

#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif

#include <QUrlQuery>

#include <univalue.h>

QString RPCExecutor::categoryClass(int category)
{
    switch (category) {
    case CMD_REQUEST:
        return "cmd-request";
        break;
    case CMD_REPLY:
        return "cmd-reply";
        break;
    case CMD_ERROR:
        return "cmd-error";
        break;
    default:
        return "misc";
    }
}

void RPCExecutor::request(const QString& command)
{
    try
    {
        std::string result;
        std::string executableCommand = command.toStdString() + "\n";

        // Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply.
        if(executableCommand == "help-console\n")
        {
            Q_EMIT reply(CMD_REPLY, QString(("\n"
                "This console accepts RPC commands using the standard syntax.\n"
                "   example:    getblockhash 0\n\n"

                "This console can also accept RPC commands using parenthesized syntax.\n"
                "   example:    getblockhash(0)\n\n"

                "Commands may be nested when specified with the parenthesized syntax.\n"
                "   example:    getblock(getblockhash(0) true)\n\n"

                "A space or a comma can be used to delimit arguments for either syntax.\n"
                "   example:    getblockhash 0\n"
                "               getblockhash,0\n\n"

                "Named results can be queried with a non-quoted key string in brackets.\n"
                "   example:    getblock(getblockhash(0) true)[tx]\n\n"

                "Results without keys can be queried using an integer in brackets.\n"
                "   example:    getblock(getblockhash(0),true)[tx][0]\n\n")));
            return;
        }
        if(!ExecuteCommandLine(result, executableCommand))
        {
            Q_EMIT reply(CMD_ERROR, QString("Parse error: unbalanced ' or \""));
            return;
        }
        Q_EMIT reply(CMD_REPLY, QString::fromStdString(result));
    }
    catch (UniValue& objError)
    {
        try {
            // Nice formatting for standard-format error
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            Q_EMIT reply(CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");

        } catch (const std::runtime_error&) {
            // raised when converting to invalid type, i.e. missing code or message
            // Show raw JSON object
            Q_EMIT reply(CMD_ERROR, QString::fromStdString(objError.write()));
        }
    } catch (const std::exception& e) {
        Q_EMIT reply(CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

/**
 * Split shell command line into a list of arguments and execute the command(s).
 * Aims to emulate \c bash and friends.
 *
 * - Command nesting is possible with brackets [example: validateaddress(getnewaddress())]
 * - Arguments are delimited with whitespace or comma
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   result      stringified Result from the executed command(chain)
 * @param[in]    strCommand  Command line to split
 */
bool RPCExecutor::ExecuteCommandLine(std::string& strResult, const std::string& strCommand)
{
    std::vector< std::vector<std::string> > stack;
    stack.push_back(std::vector<std::string>());

    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_EATING_SPACES_IN_ARG,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED,
        STATE_COMMAND_EXECUTED,
        STATE_COMMAND_EXECUTED_INNER
    } state = STATE_EATING_SPACES;
    std::string curarg;
    UniValue lastResult;

    std::string strCommandTerminated = strCommand;
    if (strCommandTerminated.back() != '\n')
        strCommandTerminated += "\n";
    for(char ch: strCommandTerminated)
    {
        switch(state)
        {
            case STATE_COMMAND_EXECUTED_INNER:
            case STATE_COMMAND_EXECUTED:
            {
                bool breakParsing = true;
                switch(ch)
                {
                    case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break;
                    default:
                        if (state == STATE_COMMAND_EXECUTED_INNER)
                        {
                            if (ch != ']')
                            {
                                // append char to the current argument (which is also used for the query command)
                                curarg += ch;
                                break;
                            }
                            if (curarg.size())
                            {
                                // if we have a value query, query arrays with index and objects with a string key
                                UniValue subelement;
                                if (lastResult.isArray())
                                {
                                    for(char argch: curarg)
                                        if (!std::isdigit(argch))
                                            throw std::runtime_error("Invalid result query");
                                    subelement = lastResult[atoi(curarg.c_str())];
                                }
                                else if (lastResult.isObject())
                                    subelement = find_value(lastResult, curarg);
                                else
                                    throw std::runtime_error("Invalid result query"); //no array or object: abort
                                lastResult = subelement;
                            }

                            state = STATE_COMMAND_EXECUTED;
                            break;
                        }
                        // don't break parsing when the char is required for the next argument
                        breakParsing = false;

                        // pop the stack and return the result to the current command arguments
                        stack.pop_back();

                        // don't stringify the json in case of a string to avoid doublequotes
                        if (lastResult.isStr())
                            curarg = lastResult.get_str();
                        else
                            curarg = lastResult.write(2);

                        // if we have a non empty result, use it as stack argument otherwise as general result
                        if (curarg.size())
                        {
                            if (stack.size())
                                stack.back().push_back(curarg);
                            else
                                strResult = curarg;
                        }
                        curarg.clear();
                        // assume eating space state
                        state = STATE_EATING_SPACES;
                }
                if (breakParsing)
                    break;
            }
            case STATE_ARGUMENT: // In or after argument
            case STATE_EATING_SPACES_IN_ARG:
            case STATE_EATING_SPACES: // Handle runs of whitespace
                switch(ch)
            {
                case '"': state = STATE_DOUBLEQUOTED; break;
                case '\'': state = STATE_SINGLEQUOTED; break;
                case '\\': state = STATE_ESCAPE_OUTER; break;
                case '(': case ')': case '\n':
                    if (state == STATE_ARGUMENT)
                    {
                        if (ch == '(' && stack.size() && stack.back().size() > 0)
                            stack.push_back(std::vector<std::string>());

                        // don't allow commands after executed commands on baselevel
                        if (!stack.size())
                            throw std::runtime_error("Invalid Syntax");

                        stack.back().push_back(curarg);
                        curarg.clear();
                        state = STATE_EATING_SPACES;
                    }
                    if ((ch == ')' || ch == '\n') && stack.size() > 0)
                    {
                        std::string strPrint;
                        // Convert argument list to JSON objects in method-dependent way,
                        // and pass it along with the method name to the dispatcher.
                        JSONRPCRequest req;
                        req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
                        req.strMethod = stack.back()[0];
#ifdef ENABLE_WALLET
                        // TODO: Move this logic to WalletModel
                        if (!vpwallets.empty()) {
                            // in Qt, use always the wallet with index 0 when running with multiple wallets
                            QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(vpwallets[0]->GetName()));
                            req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
                        }
#endif
                        lastResult = tableRPC.execute(req);
                        state = STATE_COMMAND_EXECUTED;
                        curarg.clear();
                    }
                    break;
                case ' ': case ',': case '\t':
                    if(state == STATE_ARGUMENT || (state == STATE_EATING_SPACES_IN_ARG && ch == ',')) // Space ends argument
                    {
                        stack.back().push_back(curarg);
                        curarg.clear();
                    }
                    state = (ch == ',' ? STATE_EATING_SPACES_IN_ARG : STATE_EATING_SPACES);
                    break;
                default: curarg += ch; state = STATE_ARGUMENT;
            }
                break;
            case STATE_SINGLEQUOTED: // Single-quoted string
                switch(ch)
            {
                case '\'': state = STATE_ARGUMENT; break;
                default: curarg += ch;
            }
                break;
            case STATE_DOUBLEQUOTED: // Double-quoted string
                switch(ch)
            {
                case '"': state = STATE_ARGUMENT; break;
                case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
                default: curarg += ch;
            }
                break;
            case STATE_ESCAPE_OUTER: // '\' outside quotes
                curarg += ch; state = STATE_ARGUMENT;
                break;
            case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
                if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
                curarg += ch; state = STATE_DOUBLEQUOTED;
                break;
        }
    }
    switch (state) // final state
    {
        case STATE_COMMAND_EXECUTED:
            if (lastResult.isStr())
                strResult = lastResult.get_str();
            else
                strResult = lastResult.write(2);
        case STATE_ARGUMENT:
        case STATE_EATING_SPACES:
            return true;
        default: // ERROR to end in one of the other states
            return false;
    }
}
<commit_msg>[Qt] Console: don't allow empty arguments when using the comma-syntax<commit_after>// Copyright (c) 2011-2017 The Bitcoin developers
// Copyright (c) 2015-2021 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "qt/rpcexecutor.h"

#include "rpc/client.h"

#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif

#include <QUrlQuery>

#include <univalue.h>

QString RPCExecutor::categoryClass(int category)
{
    switch (category) {
    case CMD_REQUEST:
        return "cmd-request";
        break;
    case CMD_REPLY:
        return "cmd-reply";
        break;
    case CMD_ERROR:
        return "cmd-error";
        break;
    default:
        return "misc";
    }
}

void RPCExecutor::request(const QString& command)
{
    try
    {
        std::string result;
        std::string executableCommand = command.toStdString() + "\n";

        // Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply.
        if(executableCommand == "help-console\n")
        {
            Q_EMIT reply(CMD_REPLY, QString(("\n"
                "This console accepts RPC commands using the standard syntax.\n"
                "   example:    getblockhash 0\n\n"

                "This console can also accept RPC commands using parenthesized syntax.\n"
                "   example:    getblockhash(0)\n\n"

                "Commands may be nested when specified with the parenthesized syntax.\n"
                "   example:    getblock(getblockhash(0) true)\n\n"

                "A space or a comma can be used to delimit arguments for either syntax.\n"
                "   example:    getblockhash 0\n"
                "               getblockhash,0\n\n"

                "Named results can be queried with a non-quoted key string in brackets.\n"
                "   example:    getblock(getblockhash(0) true)[tx]\n\n"

                "Results without keys can be queried using an integer in brackets.\n"
                "   example:    getblock(getblockhash(0),true)[tx][0]\n\n")));
            return;
        }
        if(!ExecuteCommandLine(result, executableCommand))
        {
            Q_EMIT reply(CMD_ERROR, QString("Parse error: unbalanced ' or \""));
            return;
        }
        Q_EMIT reply(CMD_REPLY, QString::fromStdString(result));
    }
    catch (UniValue& objError)
    {
        try {
            // Nice formatting for standard-format error
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            Q_EMIT reply(CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");

        } catch (const std::runtime_error&) {
            // raised when converting to invalid type, i.e. missing code or message
            // Show raw JSON object
            Q_EMIT reply(CMD_ERROR, QString::fromStdString(objError.write()));
        }
    } catch (const std::exception& e) {
        Q_EMIT reply(CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

/**
 * Split shell command line into a list of arguments and execute the command(s).
 * Aims to emulate \c bash and friends.
 *
 * - Command nesting is possible with brackets [example: validateaddress(getnewaddress())]
 * - Arguments are delimited with whitespace or comma
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   result      stringified Result from the executed command(chain)
 * @param[in]    strCommand  Command line to split
 */
bool RPCExecutor::ExecuteCommandLine(std::string& strResult, const std::string& strCommand)
{
    std::vector< std::vector<std::string> > stack;
    stack.push_back(std::vector<std::string>());

    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_EATING_SPACES_IN_ARG,
        STATE_EATING_SPACES_IN_BRACKETS,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED,
        STATE_COMMAND_EXECUTED,
        STATE_COMMAND_EXECUTED_INNER
    } state = STATE_EATING_SPACES;
    std::string curarg;
    UniValue lastResult;

    std::string strCommandTerminated = strCommand;
    if (strCommandTerminated.back() != '\n')
        strCommandTerminated += "\n";
    for(char ch: strCommandTerminated)
    {
        switch(state)
        {
            case STATE_COMMAND_EXECUTED_INNER:
            case STATE_COMMAND_EXECUTED:
            {
                bool breakParsing = true;
                switch(ch)
                {
                    case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break;
                    default:
                        if (state == STATE_COMMAND_EXECUTED_INNER)
                        {
                            if (ch != ']')
                            {
                                // append char to the current argument (which is also used for the query command)
                                curarg += ch;
                                break;
                            }
                            if (curarg.size())
                            {
                                // if we have a value query, query arrays with index and objects with a string key
                                UniValue subelement;
                                if (lastResult.isArray())
                                {
                                    for(char argch: curarg)
                                        if (!std::isdigit(argch))
                                            throw std::runtime_error("Invalid result query");
                                    subelement = lastResult[atoi(curarg.c_str())];
                                }
                                else if (lastResult.isObject())
                                    subelement = find_value(lastResult, curarg);
                                else
                                    throw std::runtime_error("Invalid result query"); //no array or object: abort
                                lastResult = subelement;
                            }

                            state = STATE_COMMAND_EXECUTED;
                            break;
                        }
                        // don't break parsing when the char is required for the next argument
                        breakParsing = false;

                        // pop the stack and return the result to the current command arguments
                        stack.pop_back();

                        // don't stringify the json in case of a string to avoid doublequotes
                        if (lastResult.isStr())
                            curarg = lastResult.get_str();
                        else
                            curarg = lastResult.write(2);

                        // if we have a non empty result, use it as stack argument otherwise as general result
                        if (curarg.size())
                        {
                            if (stack.size())
                                stack.back().push_back(curarg);
                            else
                                strResult = curarg;
                        }
                        curarg.clear();
                        // assume eating space state
                        state = STATE_EATING_SPACES;
                }
                if (breakParsing)
                    break;
            }
            case STATE_ARGUMENT: // In or after argument
            case STATE_EATING_SPACES_IN_ARG:
            case STATE_EATING_SPACES_IN_BRACKETS:
            case STATE_EATING_SPACES: // Handle runs of whitespace
                switch(ch)
            {
                case '"': state = STATE_DOUBLEQUOTED; break;
                case '\'': state = STATE_SINGLEQUOTED; break;
                case '\\': state = STATE_ESCAPE_OUTER; break;
                case '(': case ')': case '\n':
                    if (state == STATE_EATING_SPACES_IN_ARG)
                        throw std::runtime_error("Invalid Syntax");
                    if (state == STATE_ARGUMENT)
                    {
                        if (ch == '(' && stack.size() && stack.back().size() > 0)
                            stack.push_back(std::vector<std::string>());

                        // don't allow commands after executed commands on baselevel
                        if (!stack.size())
                            throw std::runtime_error("Invalid Syntax");

                        stack.back().push_back(curarg);
                        curarg.clear();
                        state = STATE_EATING_SPACES_IN_BRACKETS;
                    }
                    if ((ch == ')' || ch == '\n') && stack.size() > 0)
                    {
                        std::string strPrint;
                        // Convert argument list to JSON objects in method-dependent way,
                        // and pass it along with the method name to the dispatcher.
                        JSONRPCRequest req;
                        req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
                        req.strMethod = stack.back()[0];
#ifdef ENABLE_WALLET
                        // TODO: Move this logic to WalletModel
                        if (!vpwallets.empty()) {
                            // in Qt, use always the wallet with index 0 when running with multiple wallets
                            QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(vpwallets[0]->GetName()));
                            req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
                        }
#endif
                        lastResult = tableRPC.execute(req);
                        state = STATE_COMMAND_EXECUTED;
                        curarg.clear();
                    }
                    break;
                case ' ': case ',': case '\t':
                    if(state == STATE_EATING_SPACES_IN_ARG && curarg.empty() && ch == ',')
                        throw std::runtime_error("Invalid Syntax");

                    else if(state == STATE_ARGUMENT) // Space ends argument
                    {
                        stack.back().push_back(curarg);
                        curarg.clear();
                    }
                    if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ',')
                    {
                        state = STATE_EATING_SPACES_IN_ARG;
                        break;
                    }
                    state = STATE_EATING_SPACES;
                    break;
                default: curarg += ch; state = STATE_ARGUMENT;
            }
                break;
            case STATE_SINGLEQUOTED: // Single-quoted string
                switch(ch)
            {
                case '\'': state = STATE_ARGUMENT; break;
                default: curarg += ch;
            }
                break;
            case STATE_DOUBLEQUOTED: // Double-quoted string
                switch(ch)
            {
                case '"': state = STATE_ARGUMENT; break;
                case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
                default: curarg += ch;
            }
                break;
            case STATE_ESCAPE_OUTER: // '\' outside quotes
                curarg += ch; state = STATE_ARGUMENT;
                break;
            case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
                if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
                curarg += ch; state = STATE_DOUBLEQUOTED;
                break;
        }
    }
    switch (state) // final state
    {
        case STATE_COMMAND_EXECUTED:
            if (lastResult.isStr())
                strResult = lastResult.get_str();
            else
                strResult = lastResult.write(2);
        case STATE_ARGUMENT:
        case STATE_EATING_SPACES:
            return true;
        default: // ERROR to end in one of the other states
            return false;
    }
}
<|endoftext|>


<commit_before>#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif

#include "xplugin.h"
#include "ltr_gui_prefs.h"
#include "utils.h"
#include <QMessageBox>
#include <QFile>
#include <QFileInfo>
#include <QFileDialog>
#include <QRegExp>

static QMessageBox::StandardButton warningMessage(const QString &message)
{
  ltr_int_log_message("XPlanr plugin install - %s\n", message.toUtf8().constData());
  return QMessageBox::warning(NULL, QString::fromUtf8("Linuxtrack"),
                                message, QMessageBox::Ok);
}

static void warn(const QString baseMsg, const QString explanation)
{
  ltr_int_log_message("XPlanr plugin install - %s(%s)\n", baseMsg.toUtf8().constData(),
                      explanation.toUtf8().constData());
  warningMessage(QString::fromUtf8("%1\nSystem says: %2").arg(baseMsg).arg(explanation));
}

static bool removePlugin(const QString targetName)
{
  QFile target(targetName);
  if(target.exists()){
    if(!target.remove()){
      warn(QString::fromUtf8("Can't remove old plugin '%1'!").arg(targetName), target.errorString());
      return false;
    }
  }
  return true;
}

static bool installPlugin(const QString sourceFile, const QString destFile)
{
  ltr_int_log_message("Going to install '%s' to '%s'...\n",
						sourceFile.toUtf8().constData(), destFile.toUtf8().constData());
  //Create destination path
  QFile src(sourceFile);
  QFile dest(destFile);
  if(!src.exists()){
    warningMessage(QString::fromUtf8("Source file '%1' doesn't exist!").arg(sourceFile));
    return false;
  }
  QFileInfo destInfo(destFile);
  QDir destDir = destInfo.dir();
  //make sure the destination path exists
  if(!destDir.exists()){
    if(!destDir.mkpath(destDir.path())){
      warningMessage(QString::fromUtf8("Can't create output directory '%1'!").arg(destDir.path()));
      return false;
    }
  }
  //check if the file exists already
  if(dest.exists()){
    if(!removePlugin(destFile)){
      return false;
    }
  }
  //copy the new file
  if(!src.copy(destFile)){
    warn(QString::fromUtf8("Can't copy file '%1' to '%2'!").arg(destFile).arg(destDir.path()), src.errorString());
    return false;
  }
  return true;
}

void XPluginInstall::on_BrowseXPlane_pressed()
{
  QString fileName = QFileDialog::getOpenFileName(this,
     QString::fromUtf8("Find XPlane executable"), QDir::homePath(), QString::fromUtf8("All Files (*)"));
  QRegExp pathRexp(QString::fromUtf8("^(.*/)[^/]+$"));
  if(pathRexp.indexIn(fileName) == -1){
    reject();
    return;
  }
  QString sourceFile32 = PrefProxy::getLibPath(QString::fromUtf8("xlinuxtrack9_32"));
  QString sourceFile = PrefProxy::getLibPath(QString::fromUtf8("xlinuxtrack9"));
  QString destPath = pathRexp.cap(1) + QString::fromUtf8("/Resources/plugins");
  if(!QFile::exists(destPath)){
    warningMessage(QString(QString::fromUtf8("Can't install XPlane plugin there:'") + fileName +
                           QString::fromUtf8("'")));
    reject();
    return;
  }

  //Check for the old plugin and remove it if exists
  QString oldPlugin = destPath + QString::fromUtf8("/xlinuxtrack.xpl");
  QFileInfo old(oldPlugin);
  if(old.exists()){
    if(!removePlugin(oldPlugin)){
      reject();
      return;
    }
  }
  destPath += QString::fromUtf8("/xlinuxtrack/");
#ifndef DARWIN
  if(installPlugin(sourceFile32, destPath + QString::fromUtf8("/lin.xpl")) &&
       installPlugin(sourceFile, destPath + QString::fromUtf8("/64/lin.xpl"))){
#else
  if(installPlugin(sourceFile, destPath + QString::fromUtf8("/mac.xpl"))){
#endif
    QMessageBox::information(NULL, QString::fromUtf8("Linuxtrack"),
      QString::fromUtf8("XPlane plugin installed successfuly!"));
  }else{
    warningMessage(QString::fromUtf8("XPlane plugin installation failed!"));
    reject();
  }
  accept();
}

<commit_msg>Fixed a typo.<commit_after>#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif

#include "xplugin.h"
#include "ltr_gui_prefs.h"
#include "utils.h"
#include <QMessageBox>
#include <QFile>
#include <QFileInfo>
#include <QFileDialog>
#include <QRegExp>

static QMessageBox::StandardButton warningMessage(const QString &message)
{
  ltr_int_log_message("XPlane plugin install - %s\n", message.toUtf8().constData());
  return QMessageBox::warning(NULL, QString::fromUtf8("Linuxtrack"),
                                message, QMessageBox::Ok);
}

static void warn(const QString baseMsg, const QString explanation)
{
  ltr_int_log_message("XPlane plugin install - %s(%s)\n", baseMsg.toUtf8().constData(),
                      explanation.toUtf8().constData());
  warningMessage(QString::fromUtf8("%1\nSystem says: %2").arg(baseMsg).arg(explanation));
}

static bool removePlugin(const QString targetName)
{
  QFile target(targetName);
  if(target.exists()){
    if(!target.remove()){
      warn(QString::fromUtf8("Can't remove old plugin '%1'!").arg(targetName), target.errorString());
      return false;
    }
  }
  return true;
}

static bool installPlugin(const QString sourceFile, const QString destFile)
{
  ltr_int_log_message("Going to install '%s' to '%s'...\n",
						sourceFile.toUtf8().constData(), destFile.toUtf8().constData());
  //Create destination path
  QFile src(sourceFile);
  QFile dest(destFile);
  if(!src.exists()){
    warningMessage(QString::fromUtf8("Source file '%1' doesn't exist!").arg(sourceFile));
    return false;
  }
  QFileInfo destInfo(destFile);
  QDir destDir = destInfo.dir();
  //make sure the destination path exists
  if(!destDir.exists()){
    if(!destDir.mkpath(destDir.path())){
      warningMessage(QString::fromUtf8("Can't create output directory '%1'!").arg(destDir.path()));
      return false;
    }
  }
  //check if the file exists already
  if(dest.exists()){
    if(!removePlugin(destFile)){
      return false;
    }
  }
  //copy the new file
  if(!src.copy(destFile)){
    warn(QString::fromUtf8("Can't copy file '%1' to '%2'!").arg(destFile).arg(destDir.path()), src.errorString());
    return false;
  }
  return true;
}

void XPluginInstall::on_BrowseXPlane_pressed()
{
  QString fileName = QFileDialog::getOpenFileName(this,
     QString::fromUtf8("Find XPlane executable"), QDir::homePath(), QString::fromUtf8("All Files (*)"));
  QRegExp pathRexp(QString::fromUtf8("^(.*/)[^/]+$"));
  if(pathRexp.indexIn(fileName) == -1){
    reject();
    return;
  }
  QString sourceFile32 = PrefProxy::getLibPath(QString::fromUtf8("xlinuxtrack9_32"));
  QString sourceFile = PrefProxy::getLibPath(QString::fromUtf8("xlinuxtrack9"));
  QString destPath = pathRexp.cap(1) + QString::fromUtf8("/Resources/plugins");
  if(!QFile::exists(destPath)){
    warningMessage(QString(QString::fromUtf8("Can't install XPlane plugin there:'") + fileName +
                           QString::fromUtf8("'")));
    reject();
    return;
  }

  //Check for the old plugin and remove it if exists
  QString oldPlugin = destPath + QString::fromUtf8("/xlinuxtrack.xpl");
  QFileInfo old(oldPlugin);
  if(old.exists()){
    if(!removePlugin(oldPlugin)){
      reject();
      return;
    }
  }
  destPath += QString::fromUtf8("/xlinuxtrack/");
#ifndef DARWIN
  if(installPlugin(sourceFile32, destPath + QString::fromUtf8("/lin.xpl")) &&
       installPlugin(sourceFile, destPath + QString::fromUtf8("/64/lin.xpl"))){
#else
  if(installPlugin(sourceFile, destPath + QString::fromUtf8("/mac.xpl"))){
#endif
    QMessageBox::information(NULL, QString::fromUtf8("Linuxtrack"),
      QString::fromUtf8("XPlane plugin installed successfuly!"));
  }else{
    warningMessage(QString::fromUtf8("XPlane plugin installation failed!"));
    reject();
  }
  accept();
}

<|endoftext|>


<commit_before>#include <stan/math/rev.hpp>
#include <gtest/gtest.h>
#include <stan/math/rev/functor/gradient.hpp>
#include <iostream>
#include <sstream>
#include <vector>
#include <stdexcept>

#define TEST_CVODES_ADAMS 1
#define TEST_CVODES_BDF 2

using std::cos;
using std::sin;

double y1(double t, double omega, double chi) { return chi * cos(omega * t); }

double dy1_domega(double t, double omega, double chi) {
  return -t * chi * sin(omega * t);
}

double dy1_dchi(double t, double omega, double chi) { return cos(omega * t); }

double y2(double t, double omega, double chi) {
  return -omega * chi * sin(omega * t);
}

double dy2_domega(double t, double omega, double chi) {
  return -chi * (sin(omega * t) + omega * t * cos(omega * t));
}

double dy2_dchi(double t, double omega, double chi) {
  return -omega * sin(omega * t);
}

struct sho_functor {
  template <typename T0, typename T1, typename T2>
  inline Eigen::Matrix<stan::return_type_t<T1, T2>, Eigen::Dynamic, 1>
  operator()(const T0& t, const Eigen::Matrix<T1, Eigen::Dynamic, 1>& y,
             std::ostream* msgs, const T2& omega) const {
    Eigen::Matrix<stan::return_type_t<T1, T2>, Eigen::Dynamic, 1> out(2);
    out << y.coeff(1), -omega * omega * y.coeff(0);
    return out;
  }
};
/*
template <int state>
class test_functor_double_var {
  int lmm_;

 public:
  explicit test_functor_double_var(int lmm) : lmm_(lmm) {}

  template <typename T>
  inline T operator()(Eigen::Matrix<T, Eigen::Dynamic, 1>& x) const {
    sho_functor sho;

    T omega = x(0);

    Eigen::VectorXd y0(2);
    y0 << 1.25, 0.0;

    double t0 = 0.0;
    std::vector<double> ts{2.5, 5.0};

    std::vector<Eigen::Matrix<T, Eigen::Dynamic, 1>> ys
        = (lmm_ == TEST_CVODES_ADAMS)
              ? stan::math::ode_adjoint(sho, y0, t0, ts, nullptr, omega)
              : stan::math::ode_bdf(sho, y0, t0, ts, nullptr, omega);

    return ys[1](state);
  }
};

TEST(StanMathOdeIntegrateODEGradMat, double_var) {
  double omega = 0.5;
  double chi = 1.25;
  double t = 5;

  Eigen::VectorXd x(1);
  x(0) = omega;

  double f;
  Eigen::VectorXd grad(1);

  stan::math::nested_rev_autodiff nested;

  {  // Adams
    test_functor_double_var<0> func1(TEST_CVODES_ADAMS);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t, omega, chi), grad(0), 1e-6);

    test_functor_double_var<1> func2(TEST_CVODES_ADAMS);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t, omega, chi), grad(0), 1e-6);
  }

  {  // bdf
    test_functor_double_var<0> func1(TEST_CVODES_BDF);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t, omega, chi), grad(0), 1e-7);

    test_functor_double_var<1> func2(TEST_CVODES_BDF);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t, omega, chi), grad(0), 1e-7);
  }
}
*/
template <int state>
class test_functor_var_double {
  int lmm_;

 public:
  explicit test_functor_var_double(int lmm) : lmm_(lmm) {}

  template <typename T>
  inline T operator()(Eigen::Matrix<T, Eigen::Dynamic, 1>& x) const {
    sho_functor sho;

    double omega = 0.5;

    Eigen::Matrix<T, Eigen::Dynamic, 1> y0(2);
    y0 << x(0), 0.0;

    double t0 = 0.0;
    std::vector<double> ts{5.0};

    std::vector<Eigen::Matrix<T, Eigen::Dynamic, 1>> ys
        = (lmm_ == TEST_CVODES_ADAMS)
        ? stan::math::ode_adjoint_tol(sho, y0, t0, ts, 1E-10, 1E-10, 10000, nullptr, omega)
              : stan::math::ode_bdf(sho, y0, t0, ts, nullptr, omega);

    return ys[0](state);
  }
};

TEST(StanMathOdeIntegrateODEGradMat, var_double) {
  double omega = 0.5;
  double chi = 1.25;
  double t = 5;

  Eigen::VectorXd x(1);
  x(0) = chi;

  double f;
  Eigen::VectorXd grad(1);

  stan::math::nested_rev_autodiff nested;
  {  // adams
    test_functor_var_double<0> func1(TEST_CVODES_ADAMS);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_dchi(t, omega, chi), grad(0), 1e-7);

    test_functor_var_double<1> func2(TEST_CVODES_ADAMS);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_dchi(t, omega, chi), grad(0), 1e-7);
  }

  {  // bdf
    test_functor_var_double<0> func1(TEST_CVODES_BDF);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_dchi(t, omega, chi), grad(0), 1e-7);

    test_functor_var_double<1> func2(TEST_CVODES_BDF);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_dchi(t, omega, chi), grad(0), 1e-7);
  }
}

template <int state>
class test_functor_var_var {
  int lmm_;

 public:
  explicit test_functor_var_var(int lmm) : lmm_(lmm) {}

  template <typename T>
  inline T operator()(Eigen::Matrix<T, Eigen::Dynamic, 1>& x) const {
    sho_functor sho;

    T omega = x(0);

    Eigen::Matrix<T, Eigen::Dynamic, 1> y0(2);
    y0 << x(1), 0.0;

    double t0 = 0.0;
    std::vector<double> ts{2.0, 5.0};

    std::vector<Eigen::Matrix<T, Eigen::Dynamic, 1>> ys
        = (lmm_ == TEST_CVODES_ADAMS)
        ? stan::math::ode_adjoint_tol(sho, y0, t0, ts, 1E-10, 1E-10, 10000,
                                      nullptr, omega)
              : stan::math::ode_bdf(sho, y0, t0, ts, nullptr, omega);

    return ys[1](state);
  }
};

TEST(StanMathOdeIntegrateODEGradMat, var_var) {
  double omega = 0.5;
  double chi = 1.25;
  double t = 5;

  Eigen::VectorXd x(2);
  x(0) = omega;
  x(1) = chi;

  double f;
  Eigen::VectorXd grad(2);

  {
    stan::math::nested_rev_autodiff nested;

    test_functor_var_var<0> func1(TEST_CVODES_ADAMS);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t, omega, chi), grad(0), 1e-7);
    EXPECT_NEAR(dy1_dchi(t, omega, chi), grad(1), 1e-7);

    test_functor_var_var<1> func2(TEST_CVODES_ADAMS);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t, omega, chi), grad(0), 1e-6);
    EXPECT_NEAR(dy2_dchi(t, omega, chi), grad(1), 1e-7);
  }

  {
    stan::math::nested_rev_autodiff nested;

    test_functor_var_var<0> func1(TEST_CVODES_BDF);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t, omega, chi), grad(0), 1e-7);
    EXPECT_NEAR(dy1_dchi(t, omega, chi), grad(1), 1e-7);

    test_functor_var_var<1> func2(TEST_CVODES_BDF);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t, omega, chi), grad(0), 1e-6);
    EXPECT_NEAR(dy2_dchi(t, omega, chi), grad(1), 1e-7);
  }
}

template <int state>
class test_functor_sum_var_var {
  int lmm_;

 public:
  explicit test_functor_sum_var_var(int lmm) : lmm_(lmm) {}

  template <typename T>
  inline T operator()(Eigen::Matrix<T, Eigen::Dynamic, 1>& x) const {
    sho_functor sho;

    T omega = x(0);

    Eigen::Matrix<T, Eigen::Dynamic, 1> y0(2);
    y0 << x(1), 0.0;

    double t0 = 0.0;
    std::vector<double> ts{2.0, 5.0};

    Eigen::VectorXd abs_tol_f(2);
    abs_tol_f << 1E-10, 1E-10;

    std::vector<Eigen::Matrix<T, Eigen::Dynamic, 1>> ys
        = (lmm_ == TEST_CVODES_ADAMS)
        ? stan::math::ode_adjoint_tol(sho, y0, t0, ts, 1E-10, 1E-10, 10000,
                                      nullptr,
                                      omega)
              : stan::math::ode_bdf(sho, y0, t0, ts, nullptr, omega);

    return stan::math::sum(ys[0](state) + ys[1](state));
  }
};

TEST(StanMathOdeIntegrateODEGradMat, sum_var_var) {
  double omega = 0.5;
  double chi = 1.25;
  double t1 = 2.0;
  double t2 = 5;

  Eigen::VectorXd x(2);
  x(0) = omega;
  x(1) = chi;

  double f;
  Eigen::VectorXd grad(2);

  {
    stan::math::nested_rev_autodiff nested;

    test_functor_sum_var_var<0> func1(TEST_CVODES_ADAMS);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t1, omega, chi) + y1(t2, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t1, omega, chi) + dy1_domega(t2, omega, chi),
                grad(0), 1e-7);
    EXPECT_NEAR(dy1_dchi(t1, omega, chi) + dy1_dchi(t2, omega, chi), grad(1),
                1e-7);

    test_functor_sum_var_var<1> func2(TEST_CVODES_ADAMS);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t1, omega, chi) + y2(t2, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t1, omega, chi) + dy2_domega(t2, omega, chi),
                grad(0), 1e-6);
    EXPECT_NEAR(dy2_dchi(t1, omega, chi) + dy2_dchi(t2, omega, chi), grad(1),
                1e-7);
  }

  {
    stan::math::nested_rev_autodiff nested;

    test_functor_sum_var_var<0> func1(TEST_CVODES_BDF);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t1, omega, chi) + y1(t2, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t1, omega, chi) + dy1_domega(t2, omega, chi),
                grad(0), 1e-7);
    EXPECT_NEAR(dy1_dchi(t1, omega, chi) + dy1_dchi(t2, omega, chi), grad(1),
                1e-7);

    test_functor_sum_var_var<1> func2(TEST_CVODES_BDF);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t1, omega, chi) + y2(t2, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t1, omega, chi) + dy2_domega(t2, omega, chi),
                grad(0), 1e-6);
    EXPECT_NEAR(dy2_dchi(t1, omega, chi) + dy2_dchi(t2, omega, chi), grad(1),
                1e-7);
  }
}
<commit_msg>enable more tests<commit_after>#include <stan/math/rev.hpp>
#include <gtest/gtest.h>
#include <stan/math/rev/functor/gradient.hpp>
#include <iostream>
#include <sstream>
#include <vector>
#include <stdexcept>

#define TEST_CVODES_ADAMS 1
#define TEST_CVODES_BDF 2

using std::cos;
using std::sin;

double y1(double t, double omega, double chi) { return chi * cos(omega * t); }

double dy1_domega(double t, double omega, double chi) {
  return -t * chi * sin(omega * t);
}

double dy1_dchi(double t, double omega, double chi) { return cos(omega * t); }

double y2(double t, double omega, double chi) {
  return -omega * chi * sin(omega * t);
}

double dy2_domega(double t, double omega, double chi) {
  return -chi * (sin(omega * t) + omega * t * cos(omega * t));
}

double dy2_dchi(double t, double omega, double chi) {
  return -omega * sin(omega * t);
}

struct sho_functor {
  template <typename T0, typename T1, typename T2>
  inline Eigen::Matrix<stan::return_type_t<T1, T2>, Eigen::Dynamic, 1>
  operator()(const T0& t, const Eigen::Matrix<T1, Eigen::Dynamic, 1>& y,
             std::ostream* msgs, const T2& omega) const {
    Eigen::Matrix<stan::return_type_t<T1, T2>, Eigen::Dynamic, 1> out(2);
    out << y.coeff(1), -omega * omega * y.coeff(0);
    return out;
  }
};

template <int state>
class test_functor_double_var {
  int lmm_;

 public:
  explicit test_functor_double_var(int lmm) : lmm_(lmm) {}

  template <typename T>
  inline T operator()(Eigen::Matrix<T, Eigen::Dynamic, 1>& x) const {
    sho_functor sho;

    T omega = x(0);

    Eigen::VectorXd y0(2);
    y0 << 1.25, 0.0;

    double t0 = 0.0;
    std::vector<double> ts{2.5, 5.0};

    std::vector<Eigen::Matrix<T, Eigen::Dynamic, 1>> ys
        = (lmm_ == TEST_CVODES_ADAMS)
        ? stan::math::ode_adjoint_tol(sho, y0, t0, ts, 1E-10, 1E-10, 10000, nullptr, omega)
              : stan::math::ode_bdf(sho, y0, t0, ts, nullptr, omega);

    return ys[1](state);
  }
};

TEST(StanMathOdeIntegrateODEGradMat, double_var) {
  double omega = 0.5;
  double chi = 1.25;
  double t = 5;

  Eigen::VectorXd x(1);
  x(0) = omega;

  double f;
  Eigen::VectorXd grad(1);

  stan::math::nested_rev_autodiff nested;

  {  // Adams
    test_functor_double_var<0> func1(TEST_CVODES_ADAMS);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t, omega, chi), grad(0), 1e-6);

    test_functor_double_var<1> func2(TEST_CVODES_ADAMS);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t, omega, chi), grad(0), 1e-6);
  }

  {  // bdf
    test_functor_double_var<0> func1(TEST_CVODES_BDF);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t, omega, chi), grad(0), 1e-7);

    test_functor_double_var<1> func2(TEST_CVODES_BDF);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t, omega, chi), grad(0), 1e-7);
  }
}

template <int state>
class test_functor_var_double {
  int lmm_;

 public:
  explicit test_functor_var_double(int lmm) : lmm_(lmm) {}

  template <typename T>
  inline T operator()(Eigen::Matrix<T, Eigen::Dynamic, 1>& x) const {
    sho_functor sho;

    double omega = 0.5;

    Eigen::Matrix<T, Eigen::Dynamic, 1> y0(2);
    y0 << x(0), 0.0;

    double t0 = 0.0;
    std::vector<double> ts{5.0};

    std::vector<Eigen::Matrix<T, Eigen::Dynamic, 1>> ys
        = (lmm_ == TEST_CVODES_ADAMS)
        ? stan::math::ode_adjoint_tol(sho, y0, t0, ts, 1E-10, 1E-10, 10000, nullptr, omega)
              : stan::math::ode_bdf(sho, y0, t0, ts, nullptr, omega);

    return ys[0](state);
  }
};

TEST(StanMathOdeIntegrateODEGradMat, var_double) {
  double omega = 0.5;
  double chi = 1.25;
  double t = 5;

  Eigen::VectorXd x(1);
  x(0) = chi;

  double f;
  Eigen::VectorXd grad(1);

  stan::math::nested_rev_autodiff nested;
  {  // adams
    test_functor_var_double<0> func1(TEST_CVODES_ADAMS);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_dchi(t, omega, chi), grad(0), 1e-7);

    test_functor_var_double<1> func2(TEST_CVODES_ADAMS);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_dchi(t, omega, chi), grad(0), 1e-7);
  }

  {  // bdf
    test_functor_var_double<0> func1(TEST_CVODES_BDF);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_dchi(t, omega, chi), grad(0), 1e-7);

    test_functor_var_double<1> func2(TEST_CVODES_BDF);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_dchi(t, omega, chi), grad(0), 1e-7);
  }
}

template <int state>
class test_functor_var_var {
  int lmm_;

 public:
  explicit test_functor_var_var(int lmm) : lmm_(lmm) {}

  template <typename T>
  inline T operator()(Eigen::Matrix<T, Eigen::Dynamic, 1>& x) const {
    sho_functor sho;

    T omega = x(0);

    Eigen::Matrix<T, Eigen::Dynamic, 1> y0(2);
    y0 << x(1), 0.0;

    double t0 = 0.0;
    std::vector<double> ts{2.0, 5.0};

    std::vector<Eigen::Matrix<T, Eigen::Dynamic, 1>> ys
        = (lmm_ == TEST_CVODES_ADAMS)
        ? stan::math::ode_adjoint_tol(sho, y0, t0, ts, 1E-10, 1E-10, 10000,
                                      nullptr, omega)
              : stan::math::ode_bdf(sho, y0, t0, ts, nullptr, omega);

    return ys[1](state);
  }
};

TEST(StanMathOdeIntegrateODEGradMat, var_var) {
  double omega = 0.5;
  double chi = 1.25;
  double t = 5;

  Eigen::VectorXd x(2);
  x(0) = omega;
  x(1) = chi;

  double f;
  Eigen::VectorXd grad(2);

  {
    stan::math::nested_rev_autodiff nested;

    test_functor_var_var<0> func1(TEST_CVODES_ADAMS);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t, omega, chi), grad(0), 1e-7);
    EXPECT_NEAR(dy1_dchi(t, omega, chi), grad(1), 1e-7);

    test_functor_var_var<1> func2(TEST_CVODES_ADAMS);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t, omega, chi), grad(0), 1e-6);
    EXPECT_NEAR(dy2_dchi(t, omega, chi), grad(1), 1e-7);
  }

  {
    stan::math::nested_rev_autodiff nested;

    test_functor_var_var<0> func1(TEST_CVODES_BDF);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t, omega, chi), grad(0), 1e-7);
    EXPECT_NEAR(dy1_dchi(t, omega, chi), grad(1), 1e-7);

    test_functor_var_var<1> func2(TEST_CVODES_BDF);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t, omega, chi), grad(0), 1e-6);
    EXPECT_NEAR(dy2_dchi(t, omega, chi), grad(1), 1e-7);
  }
}

template <int state>
class test_functor_sum_var_var {
  int lmm_;

 public:
  explicit test_functor_sum_var_var(int lmm) : lmm_(lmm) {}

  template <typename T>
  inline T operator()(Eigen::Matrix<T, Eigen::Dynamic, 1>& x) const {
    sho_functor sho;

    T omega = x(0);

    Eigen::Matrix<T, Eigen::Dynamic, 1> y0(2);
    y0 << x(1), 0.0;

    double t0 = 0.0;
    std::vector<double> ts{2.0, 5.0};

    Eigen::VectorXd abs_tol_f(2);
    abs_tol_f << 1E-10, 1E-10;

    std::vector<Eigen::Matrix<T, Eigen::Dynamic, 1>> ys
        = (lmm_ == TEST_CVODES_ADAMS)
        ? stan::math::ode_adjoint_tol(sho, y0, t0, ts, 1E-10, 1E-10, 10000,
                                      nullptr,
                                      omega)
              : stan::math::ode_bdf(sho, y0, t0, ts, nullptr, omega);

    return stan::math::sum(ys[0](state) + ys[1](state));
  }
};

TEST(StanMathOdeIntegrateODEGradMat, sum_var_var) {
  double omega = 0.5;
  double chi = 1.25;
  double t1 = 2.0;
  double t2 = 5;

  Eigen::VectorXd x(2);
  x(0) = omega;
  x(1) = chi;

  double f;
  Eigen::VectorXd grad(2);

  {
    stan::math::nested_rev_autodiff nested;

    test_functor_sum_var_var<0> func1(TEST_CVODES_ADAMS);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t1, omega, chi) + y1(t2, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t1, omega, chi) + dy1_domega(t2, omega, chi),
                grad(0), 1e-7);
    EXPECT_NEAR(dy1_dchi(t1, omega, chi) + dy1_dchi(t2, omega, chi), grad(1),
                1e-7);

    test_functor_sum_var_var<1> func2(TEST_CVODES_ADAMS);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t1, omega, chi) + y2(t2, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t1, omega, chi) + dy2_domega(t2, omega, chi),
                grad(0), 1e-6);
    EXPECT_NEAR(dy2_dchi(t1, omega, chi) + dy2_dchi(t2, omega, chi), grad(1),
                1e-7);
  }

  {
    stan::math::nested_rev_autodiff nested;

    test_functor_sum_var_var<0> func1(TEST_CVODES_BDF);
    stan::math::gradient(func1, x, f, grad);

    EXPECT_NEAR(y1(t1, omega, chi) + y1(t2, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy1_domega(t1, omega, chi) + dy1_domega(t2, omega, chi),
                grad(0), 1e-7);
    EXPECT_NEAR(dy1_dchi(t1, omega, chi) + dy1_dchi(t2, omega, chi), grad(1),
                1e-7);

    test_functor_sum_var_var<1> func2(TEST_CVODES_BDF);
    stan::math::gradient(func2, x, f, grad);

    EXPECT_NEAR(y2(t1, omega, chi) + y2(t2, omega, chi), f, 1e-8);
    EXPECT_NEAR(dy2_domega(t1, omega, chi) + dy2_domega(t2, omega, chi),
                grad(0), 1e-6);
    EXPECT_NEAR(dy2_dchi(t1, omega, chi) + dy2_dchi(t2, omega, chi), grad(1),
                1e-7);
  }
}
<|endoftext|>


<commit_before>/*
 * perf-timer.cpp
 */

#if USE_PERF_TIMER

#include "perf-timer.hpp"

#include <cassert>
#include <stdexcept>
#include <string>
#include <vector>
#include <iostream>
#include <cstdlib>

#include <linux/perf_event.h>
#include <sched.h>

extern "C" {
#include "pmu-tools/jevents/jevents.h"
#include "pmu-tools/jevents/rdpmc.h"
}

#include "table.hpp"
#include "timers.hpp"
#include "util.hpp"
#include "context.hpp"

using namespace std;

struct PerfEvent {
    enum Type { RAW, PERF } type;
    std::string name, perf_string, desc, pmu;
};

struct RunningEvent {
    rdpmc_ctx ctx;
    std::string name;
    std::string header;

    RunningEvent(const rdpmc_ctx& ctxx, const std::string& name) :
        ctx(ctxx), name{name}, header{make_header(name)}
    {}

    static std::string make_header(std::string name) {
        return name.substr(0, std::min((size_t)6, name.length()));
    }
};

static int init_count;
static vector<RunningEvent> running_events;

int do_read_events() {
    return read_events(nullptr);
}

typedef int (*walker_callback_t)(void *data, char *name, char *event, char *desc);
typedef int (*walker_t)(walker_callback_t callback, void *data);

std::vector<PerfEvent> get_events(PerfEvent::Type type, walker_t walker) {
    vector<PerfEvent> events;
    walker([](void *data, char *name, char *event, char *desc) -> int {
        ((vector<PerfEvent>*)data)->push_back(PerfEvent{PerfEvent::RAW, name, event, desc});
        return 0;
    }, &events);
    return events;
}

std::vector<PerfEvent> get_raw_events() {
    return get_events(PerfEvent::RAW, walk_events);
}

std::vector<PerfEvent> get_perf_events() {
    return get_events(PerfEvent::PERF, walk_perf_events);
}

std::vector<PerfEvent> get_all_events() {
    auto  raw = get_raw_events();
    auto perf = get_perf_events();
    std::vector<PerfEvent> ret(raw.begin(), raw.end());
    ret.insert(ret.end(), perf.begin(), perf.end());
    return ret;
}

std::string to_hex_string(long l) {
    return string_format("%lx", l);
}

/**
 * Take a perf_event_attr objects and return a string representation suitable
 * for use as an event for perf, or just for display.
 */
std::string perf_attr_to_string(const perf_event_attr* attr) {
    std::string ret;
    char* pmu = resolve_pmu(attr->type);
    ret += std::string(pmu ? pmu : "???") + "/";

#define APPEND_IF_NZ1(field) APPEND_IF_NZ2(field,field)
#define APPEND_IF_NZ2(name, field) if (attr->field) ret += std::string(#name) + "=0x" + to_hex_string(attr->field) + ","

    APPEND_IF_NZ1(config);
    APPEND_IF_NZ1(config1);
    APPEND_IF_NZ1(config2);
    APPEND_IF_NZ2(period, sample_period);
    APPEND_IF_NZ1(sample_type);
    APPEND_IF_NZ1(read_format);

    ret.at(ret.length() - 1) = '/';
    return ret;
}

PerfTimer::PerfTimer(Context& c) : TimerInfo(
        "perf",
        "A timer which uses rdpmc and the perf_events subsystem for accurate cycle measurements",
        {})
{}

PerfNow PerfTimer::delta(const PerfNow& a, const PerfNow& b) {
    PerfNow ret;
    for (unsigned i = 0; i < PerfNow::READING_COUNT; i++) {
        ret.readings[i] = a.readings[i] - b.readings[i];
    }
    return ret;
}

TimingResult PerfTimer::to_result(const PerfTimer& ti, PerfNow delta) {
    size_t count = running_events.size();
    vector<double> results;
    results.resize(count);
    for (size_t i = 0; i < count; i++) {
        results[i] = delta.readings[i];
    }
    return { results };
}

/**
 * modify the event after getting in back from resolve event, e.g.,
 * to remove the period, exclude kernel mode if necessary, etc
 */
void fixup_event(perf_event_attr* attr, bool user_only) {
    attr->sample_period = 0;
    attr->pinned = 1;
    if (user_only) {
        attr->exclude_kernel = 1;
    }
}

void print_caps(ostream& os, const rdpmc_ctx& ctx) {
    os << "caps:" <<
            " R:" << ctx.buf->cap_user_rdpmc <<
            " UT:" << ctx.buf->cap_user_time <<
            " ZT:" << ctx.buf->cap_user_time_zero <<
            " index: 0x" << to_hex_string(ctx.buf->index) << endl;
}

void PerfTimer::init(Context &c) {
    assert(init_count++ == 0);

    const TimerArgs& args = c.getTimerArgs();

    int res = do_read_events();
    if (res) {
        throw std::runtime_error("jevents failed while reading events: " + errno_to_str(res));
    }

    bool user_only = false;

    { // init cycles event
        rdpmc_ctx ctx{};
        struct perf_event_attr cycles_attr = {
            .type = PERF_TYPE_HARDWARE,
            .size = PERF_ATTR_SIZE_VER0,
            .config = PERF_COUNT_HW_CPU_CYCLES
        };
        if (rdpmc_open_attr(&cycles_attr, &ctx, nullptr)) {
            // maybe it failed because we try to get kernel cycles too, and perf_event_paranoid is >= 2
            // so try again excluding kernel to see if that works
            cycles_attr.exclude_kernel = 1;
            if (rdpmc_open_attr(&cycles_attr, &ctx, nullptr)) {
                throw std::runtime_error("rdpmc_open cycles failed, checked stderr for more");
            } else {
                c.out() << "Counting user-mode events only: set /proc/sys/kernel/perf_event_paranoid to 1 or less to count kernel events\n";
                user_only = true;
            }
        }

        c.out() << "Programmed cycles event, ";
        print_caps(c.out(), ctx);

        running_events.emplace_back(ctx, "Cycles");
    }

    for (auto&e : split_on_string(args.extra_events, "|")) {
        if (e.empty()) {
            continue;
        }
        if (running_events.size() == PerfNow::READING_COUNT) {
            c.err() << "Event '" << e << "' - check the available events with --list-events" << endl;
            continue;
        }

        perf_event_attr attr = {};
        if (resolve_event(e.c_str(), &attr)) {
            c.out() << "Unable to resolve event '" << e << "' - check the available events with --list-events" << endl;
        } else {
            fixup_event(&attr, user_only);
            rdpmc_ctx ctx{};
            if (rdpmc_open_attr(&attr, &ctx, nullptr)) {
                c.err() << "Failed to program event '" << e << "' (resolved to '" << perf_attr_to_string(&attr) << "')\n";
            } else {
                c.out() << "Resolved and programmed event '" << e << "' to '" << perf_attr_to_string(&attr) << "', ";
                print_caps(c.out(), ctx);

                if (ctx.buf->index == 0) {
                    c.err() << "Failed to program event '" << e << "' (index == 0, rdpmc not available)" << endl;
                    rdpmc_close(&ctx);
                } else {
                    running_events.emplace_back(ctx, e);
                }
            }
        }
    }

    assert(running_events.size() <= PerfNow::READING_COUNT);

    for (auto& e : running_events) {
        metric_names_.push_back(e.header);
    }
}

template <typename E>
void printEvents(Context& c, E event_func) {
    table::Table t;
    auto& header_row = t.newRow().add("Name").add("Event string");
    if (c.verbose()) {
        header_row.add("Description");
    }
    auto events  = event_func();
    for (auto e : events) {
        auto& event_row = t.newRow().add(e.name).add(e.perf_string);
        if (c.verbose()) {
            event_row.add(e.desc);
        }
    }
    c.out() << t.str();
}

void PerfTimer::listEvents(Context& c) {
    const char *dashes = "----------------------------------------------\n";
    c.out() << dashes << "Generic perf HW events\n" << dashes << endl;
    printEvents(c, get_perf_events);
    c.out() << "\n\n";
    c.out() << dashes << "Raw CPU-specific PMU events\n" << dashes << endl;
    printEvents(c, get_raw_events);
}

PerfTimer::now_t PerfTimer::now() {
    // there is an unfortunate mismatch between the one TimerInfo instance that is created, and the fact
    // that ::now is static, see issue #62
    PerfNow ret;

    unsigned i = 0;
    for (RunningEvent& e : running_events) {
        ret.readings[i++] = rdpmc_read(&e.ctx);
    }
    return ret;
}

PerfTimer::~PerfTimer() = default;

#endif // USE_PERF_TIMER

<commit_msg>allow overriding of jevents event file via env var, some additional error handling<commit_after>/*
 * perf-timer.cpp
 */

#if USE_PERF_TIMER

#include "perf-timer.hpp"

#include <cassert>
#include <stdexcept>
#include <string>
#include <vector>
#include <iostream>
#include <cstdlib>

#include <linux/perf_event.h>
#include <sched.h>

extern "C" {
#include "pmu-tools/jevents/jevents.h"
#include "pmu-tools/jevents/rdpmc.h"
}

#include "table.hpp"
#include "timers.hpp"
#include "util.hpp"
#include "context.hpp"

using namespace std;

struct PerfEvent {
    enum Type { RAW, PERF } type;
    std::string name, perf_string, desc, pmu;
};

struct RunningEvent {
    rdpmc_ctx ctx;
    std::string name;
    std::string header;

    RunningEvent(const rdpmc_ctx& ctxx, const std::string& name) :
        ctx(ctxx), name{name}, header{make_header(name)}
    {}

    static std::string make_header(std::string name) {
        return name.substr(0, std::min((size_t)6, name.length()));
    }
};

static int init_count;
static vector<RunningEvent> running_events;

void do_read_events(Context& c) {
    const char* event_file;
    if ((event_file = getenv("UARCH_BENCH_FORCE_EVENT_FILE"))) {
        c.log() << "Using forced perf events file: " << event_file << std::endl;
    }
    int res = read_events(event_file);
    if (res) {
        throw std::runtime_error(std::string("jevents failed while reading events, error ") + std::to_string(res) + ": "
                + jevent_error_to_string(res) + ". Details: " + jevent_get_error_details());
    }
}

typedef int (*walker_callback_t)(void *data, char *name, char *event, char *desc);
typedef int (*walker_t)(walker_callback_t callback, void *data);

std::vector<PerfEvent> get_events(PerfEvent::Type type, walker_t walker) {
    vector<PerfEvent> events;
    walker([](void *data, char *name, char *event, char *desc) -> int {
        ((vector<PerfEvent>*)data)->push_back(PerfEvent{PerfEvent::RAW, name, event, desc});
        return 0;
    }, &events);
    return events;
}

std::vector<PerfEvent> get_raw_events() {
    return get_events(PerfEvent::RAW, walk_events);
}

std::vector<PerfEvent> get_perf_events() {
    return get_events(PerfEvent::PERF, walk_perf_events);
}

std::vector<PerfEvent> get_all_events() {
    auto  raw = get_raw_events();
    auto perf = get_perf_events();
    std::vector<PerfEvent> ret(raw.begin(), raw.end());
    ret.insert(ret.end(), perf.begin(), perf.end());
    return ret;
}

std::string to_hex_string(long l) {
    return string_format("%lx", l);
}

/**
 * Take a perf_event_attr objects and return a string representation suitable
 * for use as an event for perf, or just for display.
 */
std::string perf_attr_to_string(const perf_event_attr* attr) {
    std::string ret;
    char* pmu = resolve_pmu(attr->type);
    ret += std::string(pmu ? pmu : "???") + "/";

#define APPEND_IF_NZ1(field) APPEND_IF_NZ2(field,field)
#define APPEND_IF_NZ2(name, field) if (attr->field) ret += std::string(#name) + "=0x" + to_hex_string(attr->field) + ","

    APPEND_IF_NZ1(config);
    APPEND_IF_NZ1(config1);
    APPEND_IF_NZ1(config2);
    APPEND_IF_NZ2(period, sample_period);
    APPEND_IF_NZ1(sample_type);
    APPEND_IF_NZ1(read_format);

    ret.at(ret.length() - 1) = '/';
    return ret;
}

PerfTimer::PerfTimer(Context& c) : TimerInfo(
        "perf",
        "A timer which uses rdpmc and the perf_events subsystem for accurate cycle measurements",
        {})
{}

PerfNow PerfTimer::delta(const PerfNow& a, const PerfNow& b) {
    PerfNow ret;
    for (unsigned i = 0; i < PerfNow::READING_COUNT; i++) {
        ret.readings[i] = a.readings[i] - b.readings[i];
    }
    return ret;
}

TimingResult PerfTimer::to_result(const PerfTimer& ti, PerfNow delta) {
    size_t count = running_events.size();
    vector<double> results;
    results.resize(count);
    for (size_t i = 0; i < count; i++) {
        results[i] = delta.readings[i];
    }
    return { results };
}

/**
 * modify the event after getting in back from resolve event, e.g.,
 * to remove the period, exclude kernel mode if necessary, etc
 */
void fixup_event(perf_event_attr* attr, bool user_only) {
    attr->sample_period = 0;
    attr->pinned = 1;
    if (user_only) {
        attr->exclude_kernel = 1;
    }
}

void print_caps(ostream& os, const rdpmc_ctx& ctx) {
    os << "caps:" <<
            " R:" << ctx.buf->cap_user_rdpmc <<
            " UT:" << ctx.buf->cap_user_time <<
            " ZT:" << ctx.buf->cap_user_time_zero <<
            " index: 0x" << to_hex_string(ctx.buf->index) << endl;
}

void PerfTimer::init(Context &c) {
    assert(init_count++ == 0);

    const TimerArgs& args = c.getTimerArgs();

    do_read_events(c);

    bool user_only = false;

    { // init cycles event
        rdpmc_ctx ctx{};
        struct perf_event_attr cycles_attr = {
            .type = PERF_TYPE_HARDWARE,
            .size = PERF_ATTR_SIZE_VER0,
            .config = PERF_COUNT_HW_CPU_CYCLES
        };
        if (rdpmc_open_attr(&cycles_attr, &ctx, nullptr)) {
            // maybe it failed because we try to get kernel cycles too, and perf_event_paranoid is >= 2
            // so try again excluding kernel to see if that works
            cycles_attr.exclude_kernel = 1;
            if (rdpmc_open_attr(&cycles_attr, &ctx, nullptr)) {
                throw std::runtime_error("rdpmc_open cycles failed, checked stderr for more");
            } else {
                c.out() << "Counting user-mode events only: set /proc/sys/kernel/perf_event_paranoid to 1 or less to count kernel events\n";
                user_only = true;
            }
        }

        c.out() << "Programmed cycles event, ";
        print_caps(c.out(), ctx);

        running_events.emplace_back(ctx, "Cycles");
    }

    for (auto&e : split_on_string(args.extra_events, "|")) {
        if (e.empty()) {
            continue;
        }
        if (running_events.size() == PerfNow::READING_COUNT) {
            c.err() << "Event '" << e << "' - check the available events with --list-events" << endl;
            continue;
        }

        perf_event_attr attr = {};
        if (resolve_event(e.c_str(), &attr)) {
            c.out() << "Unable to resolve event '" << e << "' - check the available events with --list-events" << endl;
        } else {
            fixup_event(&attr, user_only);
            rdpmc_ctx ctx{};
            if (rdpmc_open_attr(&attr, &ctx, nullptr)) {
                c.err() << "Failed to program event '" << e << "' (resolved to '" << perf_attr_to_string(&attr) << "')\n";
            } else {
                c.out() << "Resolved and programmed event '" << e << "' to '" << perf_attr_to_string(&attr) << "', ";
                print_caps(c.out(), ctx);

                if (ctx.buf->index == 0) {
                    c.err() << "Failed to program event '" << e << "' (index == 0, rdpmc not available)" << endl;
                    rdpmc_close(&ctx);
                } else {
                    running_events.emplace_back(ctx, e);
                }
            }
        }
    }

    assert(running_events.size() <= PerfNow::READING_COUNT);

    for (auto& e : running_events) {
        metric_names_.push_back(e.header);
    }
}

template <typename E>
void printEvents(Context& c, E event_func) {
    table::Table t;
    auto& header_row = t.newRow().add("Name").add("Event string");
    if (c.verbose()) {
        header_row.add("Description");
    }
    auto events  = event_func();
    for (auto e : events) {
        auto& event_row = t.newRow().add(e.name).add(e.perf_string);
        if (c.verbose()) {
            event_row.add(e.desc);
        }
    }
    c.out() << t.str();
}

void PerfTimer::listEvents(Context& c) {
    do_read_events(c); // need this before walking events or else the default lists will be used, not accounting for forced lists
    const char *dashes = "----------------------------------------------\n";
    c.out() << dashes << "Generic perf HW events\n" << dashes << endl;
    printEvents(c, get_perf_events);
    c.out() << "\n\n";
    c.out() << dashes << "Raw CPU-specific PMU events\n" << dashes << endl;
    printEvents(c, get_raw_events);
}

PerfTimer::now_t PerfTimer::now() {
    // there is an unfortunate mismatch between the one TimerInfo instance that is created, and the fact
    // that ::now is static, see issue #62
    PerfNow ret;

    unsigned i = 0;
    for (RunningEvent& e : running_events) {
        ret.readings[i++] = rdpmc_read(&e.ctx);
    }
    return ret;
}

PerfTimer::~PerfTimer() = default;

#endif // USE_PERF_TIMER

<|endoftext|>


<commit_before>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2014 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 "qtcamgstsample.h"
#include <gst/gst.h>
#include <QDebug>

class QtCamGstSamplePrivate {
public:
  GstBuffer *buffer;
  GstCaps *caps;
#if GST_CHECK_VERSION(1,0,0)
  GstMapInfo info;
  bool mapped;
#endif
};

QtCamGstSample::QtCamGstSample(GstBuffer *buffer, GstCaps *caps) :
  d_ptr(new QtCamGstSamplePrivate) {

  d_ptr->buffer = gst_buffer_ref(buffer);
  d_ptr->caps = gst_caps_ref(caps);

#if GST_CHECK_VERSION(1,0,0)
  d_ptr->mapped = false;
#endif
}

QtCamGstSample::~QtCamGstSample() {
#if GST_CHECK_VERSION(1,0,0)
  if (d_ptr->mapped) {
    gst_buffer_unmap (d_ptr->buffer, &d_ptr->info);
    d_ptr->mapped = false;
  }
#endif
  gst_caps_unref(d_ptr->caps);
  gst_buffer_unref(d_ptr->buffer);

  delete d_ptr; d_ptr = 0;
}

GstBuffer *QtCamGstSample::buffer() const {
  return d_ptr->buffer;
}

GstCaps *QtCamGstSample::caps() const {
  return d_ptr->caps;
}

qint32 QtCamGstSample::width() const {
  const GstStructure *s = gst_caps_get_structure (d_ptr->caps, 0);
  qint32 w = -1;
  gst_structure_get_int (s, "width", &w);

  return w;
}

qint32 QtCamGstSample::height() const {
  const GstStructure *s = gst_caps_get_structure (d_ptr->caps, 0);
  qint32 h = -1;
  gst_structure_get_int (s, "height", &h);

  return h;
}

const uchar *QtCamGstSample::data() {
#if GST_CHECK_VERSION(1,0,0)
  if (!d_ptr->mapped) {
    if (!gst_buffer_map (d_ptr->buffer, &d_ptr->info, GST_MAP_READ)) {
      qCritical() << "Failed to map buffer";
      return NULL;
    }

    d_ptr->mapped = true;
  }

  return d_ptr->info.data;
#else
  return GST_BUFFER_DATA (d_ptr->buffer);
#endif
}

qint64 QtCamGstSample::size() {
#if GST_CHECK_VERSION(1,0,0)
  return gst_buffer_get_size (d_ptr->buffer);
#else
  return GST_BUFFER_SIZE (d_ptr->buffer);
#endif
}

<commit_msg>qtcamera: parse width and height when we create QtCamGstSample<commit_after>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2014 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 "qtcamgstsample.h"
#include <gst/gst.h>
#include <QDebug>

class QtCamGstSamplePrivate {
public:
  GstBuffer *buffer;
  GstCaps *caps;
  qint32 width;
  qint32 height;
  GstVideoFormat format;

#if GST_CHECK_VERSION(1,0,0)
  GstMapInfo info;
  bool mapped;
#endif
};

QtCamGstSample::QtCamGstSample(GstBuffer *buffer, GstCaps *caps) :
  d_ptr(new QtCamGstSamplePrivate) {

  d_ptr->buffer = gst_buffer_ref(buffer);
  d_ptr->caps = gst_caps_ref(caps);

#if GST_CHECK_VERSION(1,0,0)
  d_ptr->mapped = false;
#endif

  d_ptr->width = -1;
  d_ptr->height = -1;
  d_ptr->format = GST_VIDEO_FORMAT_UNKNOWN;

#if GST_CHECK_VERSION(1,0,0)
  GstVideoInfo info;
  if (!gst_video_info_from_caps (&info, d_ptr->caps)) {
    qCritical() << "Failed to parse GStreamer caps";
  } else {
    d_ptr->width = info.width;
    d_ptr->height = info.height;
    d_ptr->format = info.finfo->format;
  }
#else
  if (!gst_video_format_parse_caps (d_ptr->caps, &d_ptr->format, &d_ptr->width, &d_ptr->height)) {
    qCritical() << "Failed to parse GStreamer caps";
  }
#endif
}

QtCamGstSample::~QtCamGstSample() {
#if GST_CHECK_VERSION(1,0,0)
  if (d_ptr->mapped) {
    gst_buffer_unmap (d_ptr->buffer, &d_ptr->info);
    d_ptr->mapped = false;
  }
#endif
  gst_caps_unref(d_ptr->caps);
  gst_buffer_unref(d_ptr->buffer);

  delete d_ptr; d_ptr = 0;
}

GstBuffer *QtCamGstSample::buffer() const {
  return d_ptr->buffer;
}

GstCaps *QtCamGstSample::caps() const {
  return d_ptr->caps;
}

qint32 QtCamGstSample::width() const {
  return d_ptr->width;
}

qint32 QtCamGstSample::height() const {
  return d_ptr->height;
}

const uchar *QtCamGstSample::data() {
#if GST_CHECK_VERSION(1,0,0)
  if (!d_ptr->mapped) {
    if (!gst_buffer_map (d_ptr->buffer, &d_ptr->info, GST_MAP_READ)) {
      qCritical() << "Failed to map buffer";
      return NULL;
    }

    d_ptr->mapped = true;
  }

  return d_ptr->info.data;
#else
  return GST_BUFFER_DATA (d_ptr->buffer);
#endif
}

qint64 QtCamGstSample::size() {
#if GST_CHECK_VERSION(1,0,0)
  return gst_buffer_get_size (d_ptr->buffer);
#else
  return GST_BUFFER_SIZE (d_ptr->buffer);
#endif
}

<|endoftext|>


<commit_before>/*!
@file

@copyright Edouard Alligand and Joel Falcou 2015-2017
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_BRIGAND_FUNCTIONS_ARITHMETIC_MIN_HPP
#define BOOST_BRIGAND_FUNCTIONS_ARITHMETIC_MIN_HPP
#include <brigand/types/integral_constant.hpp>

namespace brigand
{
template <typename A, typename B>
struct min : brigand::integral_constant<
                 typename std::decay<decltype((A::value < B::value) ? A::value : B::value)>::type,
                 (A::value < B::value) ? A::value : B::value>
{
};
}
#endif
<commit_msg>Delete min.hpp<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 midnightBITS
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "pch.h"
#include <dbconn.hpp>
#include <crypt.hpp>

namespace Crypt
{
	namespace algorithm
	{
		struct SHA512
		{
			bool m_inited;
			SHA512_CTX m_ctx;
		public:
			SHA512()
			{
				m_inited = SHA512_Init(&m_ctx) != 0;
			}
			~SHA512()
			{
				if (m_inited)
					OPENSSL_cleanse(&m_ctx, sizeof(m_ctx));
			}
			bool Update(const void* msg, size_t len)
			{
				if (!m_inited) return false;
				return SHA512_Update(&m_ctx, msg, len) != 0;
			}
			bool Final(SHA512Hash::digest_t& digest)
			{
				if (!m_inited) return false;
				return SHA512_Final(digest, &m_ctx) != 0;
			}
		};

		struct MD5
		{
			bool m_inited;
			MD5_CTX m_ctx;
		public:
			MD5()
			{
				m_inited = MD5_Init(&m_ctx) != 0;
			}
			~MD5()
			{
				if (m_inited)
					OPENSSL_cleanse(&m_ctx, sizeof(m_ctx));
			}
			bool Update(const void* msg, size_t len)
			{
				if (!m_inited) return false;
				return MD5_Update(&m_ctx, msg, len) != 0;
			}
			bool Final(MD5Hash::digest_t& digest)
			{
				if (!m_inited) return false;
				return MD5_Final(digest, &m_ctx) != 0;
			}
		};
	};

	bool SHA512Hash::__crypt(const char* salt, const char* message, size_t len, digest_t &digest)
	{
		algorithm::SHA512 alg;
		if (!alg.Update(salt, SALT_LENGTH)) return false;
		if (!alg.Update(message, len)) return false;
		return alg.Final(digest);
	}

	bool MD5Hash::__crypt(const char* salt, const char* message, size_t len, digest_t &digest)
	{
		algorithm::MD5 alg;
		if (!alg.Update(salt, SALT_LENGTH)) return false;
		if (!alg.Update(message, len)) return false;
		return alg.Final(digest);
	}

	bool verify(const char* message, const char* hash)
	{
		if (!hash)
			return false;

		char alg = hash[strlen(hash) - 1];

		if (alg == SHA512Hash::ALG_ID)
			return SHA512Hash::verify(message, hash);
		if (alg == MD5Hash::ALG_ID)
			return MD5Hash::verify(message, hash);

		return false;
	}

	static char alphabet(size_t id)
	{
		static char alph[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		return alph[id];
	}

	template <class T>
	T sslrand()
	{
		T ret;
		RAND_bytes((unsigned char*)&ret, sizeof(ret));
		return ret;
	}

	static char randomChar()
	{
		return alphabet(sslrand<unsigned char>() >> 2);
	}

	void newSalt(char* salt, size_t len)
	{
		salt[--len] = 0;
		for (size_t i = 0; i < len; ++i)
			salt[i] = randomChar();
	}

	void base64_encode(const void* data, size_t len, char* output)
	{
		const unsigned char* p = (const unsigned char*)data;
		size_t pos = 0;
		unsigned int bits = 0;
		unsigned int accu = 0;
		for (size_t i = 0; i < len; ++i)
		{
			accu = (accu << 8) | (p[i] & 0xFF);
			bits += 8;
			while (bits >= 6)
			{
				bits -= 6;
				output[pos++] = alphabet((accu >> bits) & 0x3F);
			}
		}
		if (bits > 0)
		{
			accu <<= 6 - bits;
			output[pos++] = alphabet(accu & 0x3F);
		}
	}
};<commit_msg>Using more than 6 consecutive bits of randomness<commit_after>/*
 * Copyright (C) 2013 midnightBITS
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "pch.h"
#include <dbconn.hpp>
#include <crypt.hpp>

namespace Crypt
{
	namespace algorithm
	{
		struct SHA512
		{
			bool m_inited;
			SHA512_CTX m_ctx;
		public:
			SHA512()
			{
				m_inited = SHA512_Init(&m_ctx) != 0;
			}
			~SHA512()
			{
				if (m_inited)
					OPENSSL_cleanse(&m_ctx, sizeof(m_ctx));
			}
			bool Update(const void* msg, size_t len)
			{
				if (!m_inited) return false;
				return SHA512_Update(&m_ctx, msg, len) != 0;
			}
			bool Final(SHA512Hash::digest_t& digest)
			{
				if (!m_inited) return false;
				return SHA512_Final(digest, &m_ctx) != 0;
			}
		};

		struct MD5
		{
			bool m_inited;
			MD5_CTX m_ctx;
		public:
			MD5()
			{
				m_inited = MD5_Init(&m_ctx) != 0;
			}
			~MD5()
			{
				if (m_inited)
					OPENSSL_cleanse(&m_ctx, sizeof(m_ctx));
			}
			bool Update(const void* msg, size_t len)
			{
				if (!m_inited) return false;
				return MD5_Update(&m_ctx, msg, len) != 0;
			}
			bool Final(MD5Hash::digest_t& digest)
			{
				if (!m_inited) return false;
				return MD5_Final(digest, &m_ctx) != 0;
			}
		};
	};

	bool SHA512Hash::__crypt(const char* salt, const char* message, size_t len, digest_t &digest)
	{
		algorithm::SHA512 alg;
		if (!alg.Update(salt, SALT_LENGTH)) return false;
		if (!alg.Update(message, len)) return false;
		return alg.Final(digest);
	}

	bool MD5Hash::__crypt(const char* salt, const char* message, size_t len, digest_t &digest)
	{
		algorithm::MD5 alg;
		if (!alg.Update(salt, SALT_LENGTH)) return false;
		if (!alg.Update(message, len)) return false;
		return alg.Final(digest);
	}

	bool verify(const char* message, const char* hash)
	{
		if (!hash)
			return false;

		char alg = hash[strlen(hash) - 1];

		if (alg == SHA512Hash::ALG_ID)
			return SHA512Hash::verify(message, hash);
		if (alg == MD5Hash::ALG_ID)
			return MD5Hash::verify(message, hash);

		return false;
	}

	static char alphabet(size_t id)
	{
		static char alph[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		return alph[id];
	}

	template <class T>
	T sslrand()
	{
		T ret;
		RAND_bytes((unsigned char*)&ret, sizeof(ret));
		return ret;
	}

	static char randomChar()
	{
		// TODO : fixme!
		return alphabet(sslrand<unsigned char>() >> 2);
	}

	static void randomU32(char (&out)[4])
	{
		unsigned char ent[3];
		RAND_bytes(ent, sizeof(ent));
		out[0] = alphabet(ent[0] >> 2);
		out[1] = alphabet((ent[0] & 0x3) | (ent[1] >> 4));
		out[2] = alphabet((ent[1] & 0xF) | (ent[2] >> 6));
		out[3] = alphabet(ent[2] & 0x3F);
	}

	void newSalt(char* salt, size_t len)
	{
		char sample[4];
		salt[--len] = 0;
		size_t tmp = len / 4;
		for (size_t i = 0; i < tmp; ++i)
		{
			randomU32(sample);
			memcpy(salt, sample, 4);
			salt += 4;
		}

		tmp = len % 4;
		if (!tmp) return;

		randomU32(sample);
		memcpy(salt, sample, tmp);
	}

	void base64_encode(const void* data, size_t len, char* output)
	{
		const unsigned char* p = (const unsigned char*)data;
		size_t pos = 0;
		unsigned int bits = 0;
		unsigned int accu = 0;
		for (size_t i = 0; i < len; ++i)
		{
			accu = (accu << 8) | (p[i] & 0xFF);
			bits += 8;
			while (bits >= 6)
			{
				bits -= 6;
				output[pos++] = alphabet((accu >> bits) & 0x3F);
			}
		}
		if (bits > 0)
		{
			accu <<= 6 - bits;
			output[pos++] = alphabet(accu & 0x3F);
		}
	}
};<|endoftext|>


<commit_before>/*
    This file is part of libkdepim.

    Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include <libkdepim/diffalgo.h>
#include <QList>

using namespace KPIM;

void DiffAlgo::begin()
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->begin();
}

void DiffAlgo::end()
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->end();
}

void DiffAlgo::setLeftSourceTitle( const QString &title )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->setLeftSourceTitle( title );
}

void DiffAlgo::setRightSourceTitle( const QString &title )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->setRightSourceTitle( title );
}

void DiffAlgo::additionalLeftField( const QString &id, const QString &value )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->additionalLeftField( id, value );
}

void DiffAlgo::additionalRightField( const QString &id, const QString &value )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->additionalRightField( id, value );
}

void DiffAlgo::conflictField( const QString &id, const QString &leftValue,
                                 const QString &rightValue )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->conflictField( id, leftValue, rightValue );
}

void DiffAlgo::addDisplay( DiffAlgoDisplay *display )
{
  if ( !mDisplays.contains( display )  )
    mDisplays.append( display );
}

void DiffAlgo::removeDisplay( DiffAlgoDisplay *display )
{
  mDisplays.removeAll( display );
}
<commit_msg>Need memcpy. Missing include header<commit_after>/*
    This file is part of libkdepim.

    Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include <libkdepim/diffalgo.h>
#include <QList>
#include <string.h>

using namespace KPIM;

void DiffAlgo::begin()
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->begin();
}

void DiffAlgo::end()
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->end();
}

void DiffAlgo::setLeftSourceTitle( const QString &title )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->setLeftSourceTitle( title );
}

void DiffAlgo::setRightSourceTitle( const QString &title )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->setRightSourceTitle( title );
}

void DiffAlgo::additionalLeftField( const QString &id, const QString &value )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->additionalLeftField( id, value );
}

void DiffAlgo::additionalRightField( const QString &id, const QString &value )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->additionalRightField( id, value );
}

void DiffAlgo::conflictField( const QString &id, const QString &leftValue,
                                 const QString &rightValue )
{
  QList<DiffAlgoDisplay*>::Iterator it;
  for ( it = mDisplays.begin(); it != mDisplays.end(); ++it )
    (*it)->conflictField( id, leftValue, rightValue );
}

void DiffAlgo::addDisplay( DiffAlgoDisplay *display )
{
  if ( !mDisplays.contains( display )  )
    mDisplays.append( display );
}

void DiffAlgo::removeDisplay( DiffAlgoDisplay *display )
{
  mDisplays.removeAll( display );
}
<|endoftext|>


<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM 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) version 2.1 dated February 1999.

#ifndef MFEM_BLOCKVECTOR
#define MFEM_BLOCKVECTOR

#include "../config/config.hpp"
#include "../general/array.hpp"
#include "vector.hpp"

namespace mfem
{

//! @class BlockVector
/*
 * \brief A class to handle Vectors in a block fashion
 *
 * All data is contained in Vector::data, while blockVector is just a viewer for this data
 *
 */
class BlockVector: public Vector
{
protected:

   //! Number of blocks in the blockVector
   int numBlocks;
   //! Offset for each block start. (length numBlocks+1)
   /**
    * blockOffsets[i+1] - blockOffsets[i] is the size of block i.
    */
   const int *blockOffsets;
   //! array of Vector objects used to extract blocks without allocating memory.
   Vector *blocks;

   void SetBlocks();

public:
   //! empty constructor
   BlockVector();

   //! Constructor
   /**
    * bOffsets is an array of integers (length nBlocks+1) that tells the offsets
    * of each block start.
    */
   BlockVector(const Array<int> & bOffsets);

   //! Copy constructor
   BlockVector(const BlockVector & block);

   //! View constructor
   /*
    * data is an array of double of length at least blockOffsets[numBlocks] that
    * contain all the values of the monolithic vector.  bOffsets is an array of
    * integers (length nBlocks+1) that tells the offsets of each block start.
    * nBlocks is the number of blocks.
    */
   BlockVector(double *data, const Array<int> & bOffsets);

   //! Assignment operator. this and original must have the same block structure.
   BlockVector & operator=(const BlockVector & original);
   //! Set each entry of this equal to val
   BlockVector & operator=(double val);

   //! Destructor
   ~BlockVector();

   //! Get the i-th vector in the block.
   Vector & GetBlock(int i) { return blocks[i]; }
   //! Get the i-th vector in the block (const version).
   const Vector & GetBlock(int i) const { return blocks[i]; }

   //! Get the i-th vector in the block
   void GetBlockView(int i, Vector & blockView);

   int BlockSize(int i) { return blockOffsets[i+1] - blockOffsets[i];}

   //! Update method
   /**
    * data is an array of double of length at least blockOffsets[numBlocks] that
    * contain all the values of the monolithic vector.  bOffsets is an array of
    * integers (length nBlocks+1) that tells the offsets of each block start.
    * nBlocks is the number of blocks.
    */
   void Update(double *data, const Array<int> & bOffsets);

   /// Update a BlockVector with new @a bOffsets and make sure it owns its data.
   /** The block-vector will be re-allocated if either:
       - the offsets @a bOffsets are different from the current offsets, or
       - currently, the block-vector does not own its data, or
       - @a force is set to true. */
   void Update(const Array<int> &bOffsets, bool force = false);
};

}

#endif /* MFEM_BLOCKVECTOR */
<commit_msg>Update a few comments in class BlockVector.<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM 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) version 2.1 dated February 1999.

#ifndef MFEM_BLOCKVECTOR
#define MFEM_BLOCKVECTOR

#include "../config/config.hpp"
#include "../general/array.hpp"
#include "vector.hpp"

namespace mfem
{

//! @class BlockVector
/**
 * \brief A class to handle Vectors in a block fashion
 *
 * All data is contained in Vector::data, while blockVector is just a viewer for
 * this data.
 *
 */
class BlockVector: public Vector
{
protected:

   //! Number of blocks in the blockVector
   int numBlocks;
   //! Offset for each block start. (length numBlocks+1)
   /**
    * blockOffsets[i+1] - blockOffsets[i] is the size of block i.
    *
    * This array is not owned.
    */
   const int *blockOffsets;
   //! array of Vector objects used to extract blocks without allocating memory.
   /** This array is owned. */
   Vector *blocks;

   void SetBlocks();

public:
   //! empty constructor
   BlockVector();

   //! Constructor
   /**
    * bOffsets is an array of integers (length nBlocks+1) that tells the offsets
    * of each block start.
    */
   BlockVector(const Array<int> & bOffsets);

   //! Copy constructor
   BlockVector(const BlockVector & block);

   //! View constructor
   /*
    * data is an array of double of length at least blockOffsets[numBlocks] that
    * contain all the values of the monolithic vector.  bOffsets is an array of
    * integers (length nBlocks+1) that tells the offsets of each block start.
    * nBlocks is the number of blocks.
    */
   BlockVector(double *data, const Array<int> & bOffsets);

   //! Assignment operator. this and original must have the same block structure.
   BlockVector & operator=(const BlockVector & original);
   //! Set each entry of this equal to val
   BlockVector & operator=(double val);

   //! Destructor
   ~BlockVector();

   //! Get the i-th vector in the block.
   Vector & GetBlock(int i) { return blocks[i]; }
   //! Get the i-th vector in the block (const version).
   const Vector & GetBlock(int i) const { return blocks[i]; }

   //! Get the i-th vector in the block
   void GetBlockView(int i, Vector & blockView);

   int BlockSize(int i) { return blockOffsets[i+1] - blockOffsets[i];}

   //! Update method
   /**
    * data is an array of double of length at least blockOffsets[numBlocks] that
    * contain all the values of the monolithic vector.  bOffsets is an array of
    * integers (length nBlocks+1) that tells the offsets of each block start.
    * nBlocks is the number of blocks.
    */
   void Update(double *data, const Array<int> & bOffsets);

   /// Update a BlockVector with new @a bOffsets and make sure it owns its data.
   /** The block-vector will be re-allocated if either:
       - the offsets @a bOffsets are different from the current offsets, or
       - currently, the block-vector does not own its data, or
       - @a force is set to true. */
   void Update(const Array<int> &bOffsets, bool force = false);
};

}

#endif /* MFEM_BLOCKVECTOR */
<|endoftext|>