<commit_before>/*
    This code is released under the terms of the MIT license.
    See COPYING.txt for details.
*/

#include <QMessageBox>
#include <algorithm>
#include "propertieswindow.h"
#include "ui_propertieswindow.h"
#include "stuff.h"
#include "level.h"
#include "graphics.h"
#include "hexspinbox.h"
#include "tileset.h"
#include "tilesetview.h"

PropertiesWindow::PropertiesWindow(QWidget *parent, const QPixmap *tileset) :
    QDialog(parent, Qt::CustomizeWindowHint
            | Qt::WindowTitleHint
            | Qt::WindowCloseButtonHint
            | Qt::MSWindowsFixedSizeDialogHint
           ),
    ui(new Ui::PropertiesWindow),
    tileBox(new HexSpinBox(this, 2)),
    tilePalBox(new HexSpinBox(this, 2)),
    spriteBox(new HexSpinBox(this, 2)),
    spritePalBox(new HexSpinBox(this, 2)),
    tileView(new TilesetView(this, tileset, 0))
{
    ui->setupUi(this);

    // prevent window resizing
    this->layout()->setSizeConstraint(QLayout::SetFixedSize);

    // add spinboxes
    QGridLayout *layout = ui->gridLayout;
    layout->addWidget(tileBox,      2, 2, 1, 1);
    layout->addWidget(tilePalBox,   2, 5, 1, 1);
    layout->addWidget(spriteBox,    3, 2, 1, 1);
    layout->addWidget(spritePalBox, 3, 5, 1, 1);

    layout = ui->mainLayout;
    layout->addWidget(tileView, 0, 1, 1, 1);

    // add music names to other dropdown
    for (StringMap::const_iterator i = musicNames.begin(); i != musicNames.end(); i++) {
        ui->comboBox_Music->addItem(i->second, i->first);
    }

    // set up signals to automatically apply changes
    QObject::connect(ui->comboBox_TileGFX, SIGNAL(currentIndexChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(ui->comboBox_TileGFX, SIGNAL(currentIndexChanged(int)),
                     tileView, SLOT(update()));
    QObject::connect(this->tileBox, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(this->tileBox, SIGNAL(valueChanged(int)),
                     tileView, SLOT(update()));
    QObject::connect(this->tilePalBox, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(this->tilePalBox, SIGNAL(valueChanged(int)),
                     tileView, SLOT(update()));
    QObject::connect(this->spriteBox, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(this->spritePalBox, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(ui->slider_AnimSpeed, SIGNAL(valueChanged(int)),
                     this, SLOT(applySpeed(int)));
    QObject::connect(ui->slider_AnimSpeed, SIGNAL(valueChanged(int)),
                     tileView, SLOT(setAnimSpeed(int)));
    QObject::connect(ui->spinBox_Height, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(ui->spinBox_Width, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));

    // set up signals to handle width/length constraints
    QObject::connect(ui->spinBox_Height, SIGNAL(valueChanged(int)),
                     this, SLOT(setMaxLevelWidth(int)));
    QObject::connect(ui->spinBox_Width, SIGNAL(valueChanged(int)),
                     this, SLOT(setMaxLevelHeight(int)));
}

PropertiesWindow::~PropertiesWindow()
{
    delete ui;
    delete tileBox;
    delete tilePalBox;
    delete spriteBox;
    delete spritePalBox;
    delete tileView;
}

void PropertiesWindow::setMaxLevelWidth(int height) {
    ui->spinBox_Width->setMaximum(16 / height);
}

void PropertiesWindow::setMaxLevelHeight(int width) {
    ui->spinBox_Height->setMaximum(16 / width);
}

void PropertiesWindow::startEdit(leveldata_t *level) {
    this->level = NULL;

    // add graphics indices to dropdown
    ui->comboBox_TileGFX->clear();
    for (int i = 0; i < 256; i++)
        ui->comboBox_TileGFX->addItem(QString::number(i, 16).rightJustified(2, QLatin1Char('0')).toUpper()
                                         + ": banks "
                                         + QString::number(bankTable[0][i], 16).rightJustified(2, QLatin1Char('0')).toUpper() + ", "
                                         + QString::number(bankTable[1][i], 16).rightJustified(2, QLatin1Char('0')).toUpper() + ", "
                                         + QString::number(bankTable[2][i], 16).rightJustified(2, QLatin1Char('0')).toUpper() + "-"
                                         + QString::number((bankTable[2][i] + 3) & 0xFF, 16).rightJustified(2, QLatin1Char('0')).toUpper());

    // set graphics values
    ui->comboBox_TileGFX->setCurrentIndex(level->header.tileIndex);
    this->tileBox       ->setValue(level->tileset);
    this->tileBox       ->setMaximum(NUM_TILESETS - 1);
    this->tilePalBox    ->setValue(level->header.tilePal);
    this->tilePalBox    ->setMaximum(255);
    this->spriteBox     ->setValue(level->header.sprIndex);
    this->spriteBox     ->setMaximum(255);
    this->spritePalBox  ->setValue(level->header.sprPal);
    this->spritePalBox  ->setMaximum(255);
    ui->slider_AnimSpeed->setValue(level->header.animSpeed);

    // set height and width values
    ui->spinBox_Height->setValue(level->header.screensV);

    ui->spinBox_Width ->setValue(level->header.screensH);

    // set music value
    ui->comboBox_Music->setCurrentIndex(std::distance(musicNames.begin(),
                                                      musicNames.find(level->header.music)));

    // set no return value
    ui->checkBox_NoReturn->setCheckState(level->noReturn ? Qt::Checked : Qt::Unchecked);

    // save pointer
    this->level = level;
    // and original data, in case user cancels
    this->header  = level->header;
    this->tileset = level->tileset;

    this->exec();
}

void PropertiesWindow::applySpeed(int speed) {
    if (speed) {
        speed = ui->slider_AnimSpeed->maximum() - speed + 1;
        ui->label_FrameLength->setText(QString("%1 frame%2").arg(speed)
                                       .arg(speed > 1 ? "s" : ""));
    } else
        ui->label_FrameLength->setText("none");

    if (level) {
        level->header.animSpeed = speed;
        emit speedChanged(speed);
    }
}

void PropertiesWindow::applyChange() {
    if (!level) return;

    level->header.tileIndex = ui->comboBox_TileGFX->currentIndex();
    level->header.tilePal   = this->tilePalBox->value();
    level->tileset          = this->tileBox->value();
    level->header.sprIndex  = this->spriteBox->value();
    level->header.sprPal    = this->spritePalBox->value();

    // apply level size
    level->header.screensV = ui->spinBox_Height->value();
    level->header.screensH = ui->spinBox_Width ->value();

    // apply music setting
    level->header.music = ui->comboBox_Music->itemData(ui->comboBox_Music->currentIndex()).toUInt();

    // apply return flag
    level->noReturn     = ui->checkBox_NoReturn->checkState() == Qt::Checked;

    emit changed();
}

void PropertiesWindow::accept() {
    level->modified = true;
    level->modifiedRecently = true;

    QDialog::accept();
}

// discard settings
void PropertiesWindow::reject() {
    // return to original settings
    level->header  = this->header;
    level->tileset = this->tileset;

    emit changed();
    QDialog::reject();
}
<commit_msg>fix tileview animation speed<commit_after>/*
    This code is released under the terms of the MIT license.
    See COPYING.txt for details.
*/

#include <QMessageBox>
#include <algorithm>
#include "propertieswindow.h"
#include "ui_propertieswindow.h"
#include "stuff.h"
#include "level.h"
#include "graphics.h"
#include "hexspinbox.h"
#include "tileset.h"
#include "tilesetview.h"

PropertiesWindow::PropertiesWindow(QWidget *parent, const QPixmap *tileset) :
    QDialog(parent, Qt::CustomizeWindowHint
            | Qt::WindowTitleHint
            | Qt::WindowCloseButtonHint
            | Qt::MSWindowsFixedSizeDialogHint
           ),
    ui(new Ui::PropertiesWindow),
    tileBox(new HexSpinBox(this, 2)),
    tilePalBox(new HexSpinBox(this, 2)),
    spriteBox(new HexSpinBox(this, 2)),
    spritePalBox(new HexSpinBox(this, 2)),
    tileView(new TilesetView(this, tileset, 0))
{
    ui->setupUi(this);

    // prevent window resizing
    this->layout()->setSizeConstraint(QLayout::SetFixedSize);

    // add spinboxes
    QGridLayout *layout = ui->gridLayout;
    layout->addWidget(tileBox,      2, 2, 1, 1);
    layout->addWidget(tilePalBox,   2, 5, 1, 1);
    layout->addWidget(spriteBox,    3, 2, 1, 1);
    layout->addWidget(spritePalBox, 3, 5, 1, 1);

    layout = ui->mainLayout;
    layout->addWidget(tileView, 0, 1, 1, 1);

    // add music names to other dropdown
    for (StringMap::const_iterator i = musicNames.begin(); i != musicNames.end(); i++) {
        ui->comboBox_Music->addItem(i->second, i->first);
    }

    // set up signals to automatically apply changes
    QObject::connect(ui->comboBox_TileGFX, SIGNAL(currentIndexChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(ui->comboBox_TileGFX, SIGNAL(currentIndexChanged(int)),
                     tileView, SLOT(update()));
    QObject::connect(this->tileBox, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(this->tileBox, SIGNAL(valueChanged(int)),
                     tileView, SLOT(update()));
    QObject::connect(this->tilePalBox, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(this->tilePalBox, SIGNAL(valueChanged(int)),
                     tileView, SLOT(update()));
    QObject::connect(this->spriteBox, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(this->spritePalBox, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(ui->slider_AnimSpeed, SIGNAL(valueChanged(int)),
                     this, SLOT(applySpeed(int)));
    QObject::connect(ui->spinBox_Height, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));
    QObject::connect(ui->spinBox_Width, SIGNAL(valueChanged(int)),
                     this, SLOT(applyChange()));

    // set up signals to handle width/length constraints
    QObject::connect(ui->spinBox_Height, SIGNAL(valueChanged(int)),
                     this, SLOT(setMaxLevelWidth(int)));
    QObject::connect(ui->spinBox_Width, SIGNAL(valueChanged(int)),
                     this, SLOT(setMaxLevelHeight(int)));
}

PropertiesWindow::~PropertiesWindow()
{
    delete ui;
    delete tileBox;
    delete tilePalBox;
    delete spriteBox;
    delete spritePalBox;
    delete tileView;
}

void PropertiesWindow::setMaxLevelWidth(int height) {
    ui->spinBox_Width->setMaximum(16 / height);
}

void PropertiesWindow::setMaxLevelHeight(int width) {
    ui->spinBox_Height->setMaximum(16 / width);
}

void PropertiesWindow::startEdit(leveldata_t *level) {
    this->level = NULL;

    // add graphics indices to dropdown
    ui->comboBox_TileGFX->clear();
    for (int i = 0; i < 256; i++)
        ui->comboBox_TileGFX->addItem(QString::number(i, 16).rightJustified(2, QLatin1Char('0')).toUpper()
                                         + ": banks "
                                         + QString::number(bankTable[0][i], 16).rightJustified(2, QLatin1Char('0')).toUpper() + ", "
                                         + QString::number(bankTable[1][i], 16).rightJustified(2, QLatin1Char('0')).toUpper() + ", "
                                         + QString::number(bankTable[2][i], 16).rightJustified(2, QLatin1Char('0')).toUpper() + "-"
                                         + QString::number((bankTable[2][i] + 3) & 0xFF, 16).rightJustified(2, QLatin1Char('0')).toUpper());

    // set graphics values
    ui->comboBox_TileGFX->setCurrentIndex(level->header.tileIndex);
    this->tileBox       ->setValue(level->tileset);
    this->tileBox       ->setMaximum(NUM_TILESETS - 1);
    this->tilePalBox    ->setValue(level->header.tilePal);
    this->tilePalBox    ->setMaximum(255);
    this->spriteBox     ->setValue(level->header.sprIndex);
    this->spriteBox     ->setMaximum(255);
    this->spritePalBox  ->setValue(level->header.sprPal);
    this->spritePalBox  ->setMaximum(255);
    ui->slider_AnimSpeed->setValue(level->header.animSpeed);

    // set height and width values
    ui->spinBox_Height->setValue(level->header.screensV);

    ui->spinBox_Width ->setValue(level->header.screensH);

    // set music value
    ui->comboBox_Music->setCurrentIndex(std::distance(musicNames.begin(),
                                                      musicNames.find(level->header.music)));

    // set no return value
    ui->checkBox_NoReturn->setCheckState(level->noReturn ? Qt::Checked : Qt::Unchecked);

    // save pointer
    this->level = level;
    // and original data, in case user cancels
    this->header  = level->header;
    this->tileset = level->tileset;

    this->exec();
}

void PropertiesWindow::applySpeed(int speed) {
    if (speed) {
        speed = ui->slider_AnimSpeed->maximum() - speed + 1;
        ui->label_FrameLength->setText(QString("%1 frame%2").arg(speed)
                                       .arg(speed > 1 ? "s" : ""));
    } else
        ui->label_FrameLength->setText("none");

    if (level) {
        level->header.animSpeed = speed;
        emit speedChanged(speed);
    }

    tileView->setAnimSpeed(speed);
}

void PropertiesWindow::applyChange() {
    if (!level) return;

    level->header.tileIndex = ui->comboBox_TileGFX->currentIndex();
    level->header.tilePal   = this->tilePalBox->value();
    level->tileset          = this->tileBox->value();
    level->header.sprIndex  = this->spriteBox->value();
    level->header.sprPal    = this->spritePalBox->value();

    // apply level size
    level->header.screensV = ui->spinBox_Height->value();
    level->header.screensH = ui->spinBox_Width ->value();

    // apply music setting
    level->header.music = ui->comboBox_Music->itemData(ui->comboBox_Music->currentIndex()).toUInt();

    // apply return flag
    level->noReturn     = ui->checkBox_NoReturn->checkState() == Qt::Checked;

    emit changed();
}

void PropertiesWindow::accept() {
    level->modified = true;
    level->modifiedRecently = true;

    QDialog::accept();
}

// discard settings
void PropertiesWindow::reject() {
    // return to original settings
    level->header  = this->header;
    level->tileset = this->tileset;

    emit changed();
    QDialog::reject();
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_MAT_PROB_ORDERED_LOGISTIC_LPMF_HPP
#define STAN_MATH_PRIM_MAT_PROB_ORDERED_LOGISTIC_LPMF_HPP

#include <stan/math/prim/mat/fun/value_of.hpp>
#include <stan/math/prim/mat/fun/size.hpp>
#include <stan/math/prim/mat/meta/vector_seq_view.hpp>
#include <stan/math/prim/mat/err/check_ordered.hpp>
#include <stan/math/prim/scal/fun/inv_logit.hpp>
#include <stan/math/prim/scal/fun/log1p_exp.hpp>
#include <stan/math/prim/scal/fun/log_inv_logit_diff.hpp>
#include <stan/math/prim/scal/err/check_bounded.hpp>
#include <stan/math/prim/scal/err/check_finite.hpp>
#include <stan/math/prim/scal/err/check_greater.hpp>
#include <stan/math/prim/scal/err/check_consistent_sizes.hpp>
#include <stan/math/prim/scal/meta/include_summand.hpp>
#include <stan/math/prim/scal/meta/return_type.hpp>
#include <stan/math/prim/scal/meta/partials_return_type.hpp>
#include <stan/math/prim/scal/meta/operands_and_partials.hpp>
#include <stan/math/prim/scal/meta/is_constant_struct.hpp>
#include <stan/math/prim/scal/meta/scalar_seq_view.hpp>
#include <vector>

namespace stan {
namespace math {

template <typename T>
struct ordLog_helper {
  /**
   * Returns the (natural) log probability of the specified integer
   * outcome given the continuous location and specified cutpoints
   * in an ordered logistic model.
   *
   * Error-checking handled by main distribution functions, with this
   * function only called once inputs have been validated.
   *
   * @tparam T Type of location & cutpoint variables.
   * @param y Outcome.
   * @param K Number of categories.
   * @param lambda Location.
   * @param c Positive increasing vector of cutpoints.
   * @return Log probability of outcome given location and
   * cutpoints.
   */
  T logp(const int& y, const int& K, const T& lambda,
         const Eigen::Matrix<T, Eigen::Dynamic, 1>& c) {
    if (y == 1)
      return -log1p_exp(lambda - c[0]);
    else if (y == K)
      return -log1p_exp(c[K - 2] - lambda);
    else
      return log_inv_logit_diff(lambda - c[y - 2], lambda - c[y - 1]);
  }

  /**
   * Returns a vector with the gradients of the the continuous location
   * and ordered cutpoints in an ordered logistic model. The first element
   * of the vector contains the gradient for the location variable (lambda),
   * followed by the gradients for the ordered cutpoints (c).
   *
   * Error-checking handled by main distribution functions, with this
   * function only called once inputs have been validated.
   *
   * @tparam T Type of location & cutpoint variables.
   * @param y Outcome.
   * @param K Number of categories.
   * @param lambda Location.
   * @param c Positive increasing vector of cutpoints.
   * @return Vector of gradients.
   */
  Eigen::Matrix<T, Eigen::Dynamic, 1> deriv(
      const int& y, const int& K, const T& lambda,
      const Eigen::Matrix<T, Eigen::Dynamic, 1>& c) {
    using std::exp;

    Eigen::Matrix<T, Eigen::Dynamic, 1> d(
        Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(K));

    if (y == 1) {
      d[0] -= inv_logit(lambda - c[0]);
      d[1] -= d[0];
      return d;
    } else if (y == K) {
      d[0] += inv_logit(c[K - 2] - lambda);
      d[K - 1] -= d[0];
      return d;
    } else {
      d[y - 1]
          += inv(1 - exp(c[y - 1] - c[y - 2])) - inv_logit(c[y - 2] - lambda);
      d[y] += inv(1 - exp(c[y - 2] - c[y - 1])) - inv_logit(c[y - 1] - lambda);
      d[0] -= d[y] + d[y - 1];
      return d;
    }
  }
};

/**
 * Returns the (natural) log probability of the specified integer
 * outcome given the continuous location and specified cutpoints
 * in an ordered logistic model.
 *
 *
Typically the continous location
 * will be the dot product of a vector of regression coefficients
 * and a vector of predictors for the outcome.
 *
 * @tparam propto True if calculating up to a proportion.
 * @tparam T_loc Location type.
 * @tparam T_cut Cut-point type.
 * @param y Outcome.
 * @param lambda Location.
 * @param c Positive increasing vector of cutpoints.
 * @return Log probability of outcome given location and
 * cutpoints.
 * @throw std::domain_error If the outcome is not between 1 and
 * the number of cutpoints plus 2; if the cutpoint vector is
 * empty; if the cutpoint vector contains a non-positive,
 * non-finite value; or if the cutpoint vector is not sorted in
 * ascending order.
 */
template <bool propto, typename T_loc, typename T_cut>
typename return_type<T_loc, T_cut>::type ordered_logistic_lpmf(
    int y, const T_loc& lambda,
    const Eigen::Matrix<T_cut, Eigen::Dynamic, 1>& c) {
  static const char* function = "ordered_logistic";

  typedef typename stan::partials_return_type<
      T_loc, Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>::type T_partials_return;

  typedef typename Eigen::Matrix<T_partials_return, -1, 1> T_partials_vec;

  int K = c.size() + 1;

  check_bounded(function, "Random variable", y, 1, K);
  check_finite(function, "Location parameter", lambda);
  check_greater(function, "Size of cut points parameter", c.size(), 0);
  check_ordered(function, "Cut-points", c);
  check_finite(function, "Final cut-point", c(c.size() - 1));
  check_finite(function, "First cut-point", c(0));

  scalar_seq_view<T_loc> lam_vec(lambda);
  T_partials_return lam_dbl = value_of(lam_vec[0]);

  vector_seq_view<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>> c_vec(c);
  T_partials_vec c_dbl((K - 1));
  c_dbl = value_of(c_vec[0]).template cast<T_partials_return>();

  ordLog_helper<T_partials_return> ordhelp;

  T_partials_vec d = ordhelp.deriv(y, K, lam_dbl, c_dbl);

  operands_and_partials<T_loc, Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>
      ops_partials(lambda, c);

  if (!is_constant_struct<T_loc>::value)
    ops_partials.edge1_.partials_[0] = d[0];

  if (!is_constant_struct<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>::value)
    ops_partials.edge2_.partials_ = d.tail(K - 1);

  return ops_partials.build(ordhelp.logp(y, K, lam_dbl, c_dbl));
}

template <typename T_loc, typename T_cut>
typename return_type<T_loc, T_cut>::type ordered_logistic_lpmf(
    int y, const T_loc& lambda,
    const Eigen::Matrix<T_cut, Eigen::Dynamic, 1>& c) {
  return ordered_logistic_lpmf<false>(y, lambda, c);
}

/**
 * Returns the (natural) log probability of the specified array
 * of integers given the vector of continuous locations and
 * specified cutpoints in an ordered logistic model.
 *
 *
Typically the continous location
 * will be the dot product of a vector of regression coefficients
 * and a vector of predictors for the outcome.
 *
 * @tparam propto True if calculating up to a proportion.
 * @tparam T_loc Location type.
 * @tparam T_cut Cut-point type.
 * @param y Array of integers
 * @param lambda Vector of continuous location variables.
 * @param c Positive increasing vector of cutpoints.
 * @return Log probability of outcome given location and
 * cutpoints.
 * @throw std::domain_error If the outcome is not between 1 and
 * the number of cutpoints plus 2; if the cutpoint vector is
 * empty; if the cutpoint vector contains a non-positive,
 * non-finite value; or if the cutpoint vector is not sorted in
 * ascending order.
 * @throw std::invalid_argument If y and lambda are different
 * lengths.
 */
template <bool propto, typename T_loc, typename T_cut>
typename return_type<T_loc, T_cut>::type ordered_logistic_lpmf(
    const std::vector<int>& y,
    const Eigen::Matrix<T_loc, Eigen::Dynamic, 1>& lambda,
    const Eigen::Matrix<T_cut, Eigen::Dynamic, 1>& c) {
  static const char* function = "ordered_logistic";

  typedef typename stan::partials_return_type<
      Eigen::Matrix<T_loc, Eigen::Dynamic, 1>,
      Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>::type T_partials_return;

  typedef typename Eigen::Matrix<T_partials_return, -1, 1> T_partials_vec;

  int N = lambda.size();
  int K = c.size() + 1;

  check_consistent_sizes(function, "Integers", y, "Locations", lambda);
  check_bounded(function, "Random variable", y, 1, K);
  check_finite(function, "Location parameter", lambda);
  check_ordered(function, "Cut-points", c);
  check_greater(function, "Size of cut points parameter", c.size(), 0);
  check_finite(function, "Final cut-point", c(c.size() - 1));
  check_finite(function, "First cut-point", c(0));

  vector_seq_view<Eigen::Matrix<T_loc, Eigen::Dynamic, 1>> lam_vec(lambda);
  T_partials_vec lam_dbl
      = value_of(lam_vec[0]).template cast<T_partials_return>();

  vector_seq_view<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>> c_vec(c);
  T_partials_vec c_dbl((K - 1));
  c_dbl = value_of(c_vec[0]).template cast<T_partials_return>();

  ordLog_helper<T_partials_return> ordhelp;

  T_partials_return logp(0.0);
  T_partials_vec lam_deriv(N);
  T_partials_vec c_deriv(T_partials_vec::Zero(K - 1));

  for (int n = 0; n < N; ++n) {
    T_partials_vec d = ordhelp.deriv(y[n], K, lam_dbl[n], c_dbl);

    logp += ordhelp.logp(y[n], K, lam_dbl[n], c_dbl);
    lam_deriv[n] = d[0];
    c_deriv += d.tail(K - 1);
  }

  operands_and_partials<Eigen::Matrix<T_loc, Eigen::Dynamic, 1>,
                        Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>
      ops_partials(lambda, c);

  if (!is_constant_struct<Eigen::Matrix<T_loc, Eigen::Dynamic, 1>>::value)
    ops_partials.edge1_.partials_ = lam_deriv;

  if (!is_constant_struct<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>::value)
    ops_partials.edge2_.partials_ = c_deriv;

  return ops_partials.build(logp);
}

template <typename T_loc, typename T_cut>
typename return_type<T_loc, T_cut>::type ordered_logistic_lpmf(
    const std::vector<int>& y,
    const Eigen::Matrix<T_loc, Eigen::Dynamic, 1>& lambda,
    const Eigen::Matrix<T_cut, Eigen::Dynamic, 1>& c) {
  return ordered_logistic_lpmf<false>(y, lambda, c);
}

/**
 * Returns the (natural) log probability of the specified array
 * of integers given the vector of continuous locations and
 * array of specified cutpoints in an ordered logistic model.
 *
 *
Typically the continous location
 * will be the dot product of a vector of regression coefficients
 * and a vector of predictors for the outcome.
 *
 * @tparam propto True if calculating up to a proportion.
 * @tparam T_y Type of y variable (should be std::vector<int>).
 * @tparam T_loc Location type.
 * @tparam T_cut Cut-point type.
 * @param y Array of integers
 * @param lambda Vector of continuous location variables.
 * @param c array of Positive increasing vectors of cutpoints.
 * @return Log probability of outcome given location and
 * cutpoints.
 * @throw std::domain_error If the outcome is not between 1 and
 * the number of cutpoints plus 2; if the cutpoint vector is
 * empty; if the cutpoint vector contains a non-positive,
 * non-finite value; or if the cutpoint vector is not sorted in
 * ascending order.
 * @throw std::invalid_argument If y and lambda are different
 * lengths, or if y and the array of cutpoints are of different
 * lengths.
 */
template <bool propto, typename T_loc, typename T_cut>
typename return_type<T_loc, T_cut>::type ordered_logistic_lpmf(
    const std::vector<int>& y,
    const Eigen::Matrix<T_loc, Eigen::Dynamic, 1>& lambda,
    const std::vector<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>& c) {
  static const char* function = "ordered_logistic";

  typedef typename stan::partials_return_type<
      Eigen::Matrix<T_loc, Eigen::Dynamic, 1>,
      std::vector<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>>::type
      T_partials_return;

  typedef typename Eigen::Matrix<T_partials_return, -1, 1> T_partials_vec;

  int N = lambda.size();
  int K = c[0].size() + 1;

  for (int n = 0; n < N; ++n) {
    check_bounded(function, "Random variable", y[n], 1, K);
    check_greater(function, "Size of cut points parameter", c[n].size(), 0);
    check_ordered(function, "Cut-points", c[n]);
  }
  check_consistent_sizes(function, "Integers", y, "Locations", lambda);
  check_consistent_sizes(function, "Integers", y, "Cut-points", c);
  check_finite(function, "Location parameter", lambda);
  check_finite(function, "Cut-points", c);

  vector_seq_view<Eigen::Matrix<T_loc, Eigen::Dynamic, 1>> lam_vec(lambda);
  T_partials_vec lam_dbl
      = value_of(lam_vec[0]).template cast<T_partials_return>();

  vector_seq_view<std::vector<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>> c_vec(
      c);
  std::vector<T_partials_vec> c_dbl(N);
  for (int n = 0; n < N; ++n)
    c_dbl[n] = value_of(c_vec[n]).template cast<T_partials_return>();

  ordLog_helper<T_partials_return> ordhelp;

  T_partials_return logp(0.0);
  T_partials_vec lam_deriv(N);
  std::vector<T_partials_vec> c_deriv(N);

  for (int n = 0; n < N; ++n) {
    T_partials_vec d = ordhelp.deriv(y[n], K, lam_dbl[n], c_dbl[n]);

    logp += ordhelp.logp(y[n], K, lam_dbl[n], c_dbl[n]);
    lam_deriv[n] = d[0];
    c_deriv[n] = d.tail(K - 1);
  }

  operands_and_partials<Eigen::Matrix<T_loc, Eigen::Dynamic, 1>,
                        std::vector<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>>
      ops_partials(lambda, c);

  if (!is_constant_struct<Eigen::Matrix<T_loc, Eigen::Dynamic, 1>>::value)
    ops_partials.edge1_.partials_ = lam_deriv;

  if (!is_constant_struct<
          std::vector<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>>::value) {
    for (int n = 0; n < N; ++n)
      ops_partials.edge2_.partials_vec_[n] = c_deriv[n];
  }

  return ops_partials.build(logp);
}

template <typename T_loc, typename T_cut>
typename return_type<T_loc, T_cut>::type ordered_logistic_lpmf(
    const std::vector<int>& y,
    const Eigen::Matrix<T_loc, Eigen::Dynamic, 1>& lambda,
    const std::vector<Eigen::Matrix<T_cut, Eigen::Dynamic, 1>>& c) {
  return ordered_logistic_lpmf<false>(y, lambda, c);
}
}  // namespace math
}  // namespace stan
#endif
<commit_msg>Collapse to single function with vector views<commit_after>#ifndef STAN_MATH_PRIM_MAT_PROB_ORDERED_LOGISTIC_LPMF_HPP
#define STAN_MATH_PRIM_MAT_PROB_ORDERED_LOGISTIC_LPMF_HPP

#include <stan/math/prim/mat/fun/value_of.hpp>
#include <stan/math/prim/mat/fun/size.hpp>
#include <stan/math/prim/mat/meta/vector_seq_view.hpp>
#include <stan/math/prim/mat/err/check_ordered.hpp>
#include <stan/math/prim/scal/fun/inv_logit.hpp>
#include <stan/math/prim/scal/fun/log1p_exp.hpp>
#include <stan/math/prim/scal/fun/log_inv_logit_diff.hpp>
#include <stan/math/prim/scal/err/check_bounded.hpp>
#include <stan/math/prim/scal/err/check_finite.hpp>
#include <stan/math/prim/scal/err/check_greater.hpp>
#include <stan/math/prim/scal/err/check_consistent_sizes.hpp>
#include <stan/math/prim/scal/meta/include_summand.hpp>
#include <stan/math/prim/scal/meta/return_type.hpp>
#include <stan/math/prim/scal/meta/partials_return_type.hpp>
#include <stan/math/prim/scal/meta/operands_and_partials.hpp>
#include <stan/math/prim/scal/meta/is_constant_struct.hpp>
#include <stan/math/prim/scal/meta/scalar_seq_view.hpp>
#include <vector>

namespace stan {
namespace math {

template <typename T>
struct ordLog_helper {
  /**
   * Returns the (natural) log probability of the specified integer
   * outcome given the continuous location and specified cutpoints
   * in an ordered logistic model.
   *
   * Error-checking handled by main distribution functions, with this
   * function only called once inputs have been validated.
   *
   * @tparam T Type of location & cutpoint variables.
   * @param y Outcome.
   * @param K Number of categories.
   * @param lambda Location.
   * @param c Positive increasing vector of cutpoints.
   * @return Log probability of outcome given location and
   * cutpoints.
   */
  T logp(const int& y, const int& K, const T& lambda,
         const Eigen::Matrix<T, Eigen::Dynamic, 1>& c) {
    if (y == 1)
      return -log1p_exp(lambda - c[0]);
    else if (y == K)
      return -log1p_exp(c[K - 2] - lambda);
    else
      return log_inv_logit_diff(lambda - c[y - 2], lambda - c[y - 1]);
  }

  /**
   * Returns a vector with the gradients of the the continuous location
   * and ordered cutpoints in an ordered logistic model. The first element
   * of the vector contains the gradient for the location variable (lambda),
   * followed by the gradients for the ordered cutpoints (c).
   *
   * Error-checking handled by main distribution functions, with this
   * function only called once inputs have been validated.
   *
   * @tparam T Type of location & cutpoint variables.
   * @param y Outcome.
   * @param K Number of categories.
   * @param lambda Location.
   * @param c Positive increasing vector of cutpoints.
   * @return Vector of gradients.
   */
  Eigen::Matrix<T, Eigen::Dynamic, 1> deriv(
      const int& y, const int& K, const T& lambda,
      const Eigen::Matrix<T, Eigen::Dynamic, 1>& c) {
    using std::exp;

    Eigen::Matrix<T, Eigen::Dynamic, 1> d(
        Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(K));

    if (y == 1) {
      d[0] -= inv_logit(lambda - c[0]);
      d[1] -= d[0];
      return d;
    } else if (y == K) {
      d[0] += inv_logit(c[K - 2] - lambda);
      d[K - 1] -= d[0];
      return d;
    } else {
      d[y - 1]
          += inv(1 - exp(c[y - 1] - c[y - 2])) - inv_logit(c[y - 2] - lambda);
      d[y] += inv(1 - exp(c[y - 2] - c[y - 1])) - inv_logit(c[y - 1] - lambda);
      d[0] -= d[y] + d[y - 1];
      return d;
    }
  }
};

/**
 * Returns the (natural) log probability of the specified array
 * of integers given the vector of continuous locations and
 * specified cutpoints in an ordered logistic model.
 *
 *
Typically the continous location
 * will be the dot product of a vector of regression coefficients
 * and a vector of predictors for the outcome.
 *
 * @tparam propto True if calculating up to a proportion.
 * @tparam T_loc Location type.
 * @tparam T_cut Cut-point type.
 * @param y Array of integers
 * @param lambda Vector of continuous location variables.
 * @param c Positive increasing vector of cutpoints.
 * @return Log probability of outcome given location and
 * cutpoints.
 * @throw std::domain_error If the outcome is not between 1 and
 * the number of cutpoints plus 2; if the cutpoint vector is
 * empty; if the cutpoint vector contains a non-positive,
 * non-finite value; or if the cutpoint vector is not sorted in
 * ascending order.
 * @throw std::invalid_argument If y and lambda are different
 * lengths.
 */

template <bool propto, typename T_y, typename T_loc, typename T_cut>
typename return_type<T_loc, T_cut>::type ordered_logistic_lpmf(
    const T_y& y, const T_loc& lambda, const T_cut& c) {
  static const char* function = "ordered_logistic";

  typedef typename stan::partials_return_type<T_loc, T_cut>::type
    T_partials_return;
  typedef typename Eigen::Matrix<T_partials_return, -1, 1>
    T_partials_vec;

  scalar_seq_view<T_loc> lam_vec(lambda);
  scalar_seq_view<T_y> y_vec(y);
  vector_seq_view<T_cut> c_vec(c);

  int K = c_vec[0].size() + 1;
  int N = length(lambda);

  check_consistent_sizes(function, "Integers", y, "Locations", lambda);

  for (size_t n = 0; n < N; n++) {
    check_bounded(function, "Random variable", y_vec[n], 1, K);
    check_finite(function, "Location parameter", lam_vec[n]);
  }

  for (size_t i = 0, size_ = length(c_vec); i < size_; i++) {
    check_ordered(function, "Cut-points", c_vec[i]);
    check_greater(function, "Size of cut points parameter", c_vec[i].size(), 0);
    check_finite(function, "Final cut-point", c_vec[i](c_vec[i].size() - 1));
    check_finite(function, "First cut-point", c_vec[i](0));
  }

  ordLog_helper<T_partials_return> ordhelp;
  operands_and_partials<T_loc, T_cut> ops_partials(lambda, c);

  T_partials_return logp(0.0);

  for (int n = 0; n < N; ++n) {
    for (size_t i = 0, size_ = length(c_vec); i < size_; i++) {
      T_partials_return lam_dbl = value_of(lam_vec[n]);
      T_partials_vec c_dbl = value_of(c_vec[i]).template
                                                  cast<T_partials_return>();
      T_partials_vec d = ordhelp.deriv(y_vec[n], K, lam_dbl, c_dbl);

      logp += ordhelp.logp(y_vec[n], K, lam_dbl, c_dbl);

    if (!is_constant_struct<T_loc>::value)
      ops_partials.edge1_.partials_[n] = d[0];

    if (!is_constant_struct<T_cut>::value)
      ops_partials.edge2_.partials_vec_[n] += d.tail(K - 1);
    }
  }
  return ops_partials.build(logp);
}

template <typename T_y, typename T_loc, typename T_cut>
typename return_type<T_loc, T_cut>::type ordered_logistic_lpmf(
    const T_y& y, const T_loc& lambda, const T_cut& c) {
  return ordered_logistic_lpmf<false>(y, lambda, c);
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>//=- AArch64RedundantCopyElimination.cpp - Remove useless copy for AArch64 -=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
// This pass removes unnecessary zero copies in BBs that are targets of
// cbz/cbnz instructions. For instance, the copy instruction in the code below
// can be removed because the CBZW jumps to BB#2 when W0 is zero.
//  BB#1:
//    CBZW %W0, <BB#2>
//  BB#2:
//    %W0 = COPY %WZR
// This pass should be run after register allocation.
//
// FIXME: This should be extended to handle any constant other than zero. E.g.,
//   cmp w0, #1
//     b.eq .BB1
//   BB1:
//     mov w0, #1
//
// FIXME: This could also be extended to check the whole dominance subtree below
// the comparison if the compile time regression is acceptable.
//
//===----------------------------------------------------------------------===//

#include "AArch64.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

#define DEBUG_TYPE "aarch64-copyelim"

STATISTIC(NumCopiesRemoved, "Number of copies removed.");

namespace {
class AArch64RedundantCopyElimination : public MachineFunctionPass {
  const MachineRegisterInfo *MRI;
  const TargetRegisterInfo *TRI;

public:
  static char ID;
  AArch64RedundantCopyElimination() : MachineFunctionPass(ID) {
    initializeAArch64RedundantCopyEliminationPass(
        *PassRegistry::getPassRegistry());
  }
  bool optimizeCopy(MachineBasicBlock *MBB);
  bool runOnMachineFunction(MachineFunction &MF) override;
  MachineFunctionProperties getRequiredProperties() const override {
    return MachineFunctionProperties().set(
        MachineFunctionProperties::Property::NoVRegs);
  }
  StringRef getPassName() const override {
    return "AArch64 Redundant Copy Elimination";
  }
};
char AArch64RedundantCopyElimination::ID = 0;
}

INITIALIZE_PASS(AArch64RedundantCopyElimination, "aarch64-copyelim",
                "AArch64 redundant copy elimination pass", false, false)

static bool guaranteesZeroRegInBlock(MachineInstr &MI, MachineBasicBlock *MBB) {
  unsigned Opc = MI.getOpcode();
  // Check if the current basic block is the target block to which the
  // CBZ/CBNZ instruction jumps when its Wt/Xt is zero.
  if ((Opc == AArch64::CBZW || Opc == AArch64::CBZX) &&
      MBB == MI.getOperand(1).getMBB())
    return true;
  else if ((Opc == AArch64::CBNZW || Opc == AArch64::CBNZX) &&
           MBB != MI.getOperand(1).getMBB())
    return true;

  return false;
}

bool AArch64RedundantCopyElimination::optimizeCopy(MachineBasicBlock *MBB) {
  // Check if the current basic block has a single predecessor.
  if (MBB->pred_size() != 1)
    return false;

  MachineBasicBlock *PredMBB = *MBB->pred_begin();
  MachineBasicBlock::iterator CompBr = PredMBB->getLastNonDebugInstr();
  if (CompBr == PredMBB->end() || PredMBB->succ_size() != 2)
    return false;

  ++CompBr;
  do {
    --CompBr;
    if (guaranteesZeroRegInBlock(*CompBr, MBB))
      break;
  } while (CompBr != PredMBB->begin() && CompBr->isTerminator());

  // We've not found a CBZ/CBNZ, time to bail out.
  if (!guaranteesZeroRegInBlock(*CompBr, MBB))
    return false;

  unsigned TargetReg = CompBr->getOperand(0).getReg();
  if (!TargetReg)
    return false;
  assert(TargetRegisterInfo::isPhysicalRegister(TargetReg) &&
         "Expect physical register");

  // Remember all registers aliasing with TargetReg.
  SmallSetVector<unsigned, 8> TargetRegs;
  for (MCRegAliasIterator AI(TargetReg, TRI, true); AI.isValid(); ++AI)
    TargetRegs.insert(*AI);

  bool Changed = false;
  MachineBasicBlock::iterator LastChange = MBB->begin();
  unsigned SmallestDef = TargetReg;
  // Remove redundant Copy instructions unless TargetReg is modified.
  for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;) {
    MachineInstr *MI = &*I;
    ++I;
    if (MI->isCopy() && MI->getOperand(0).isReg() &&
        MI->getOperand(1).isReg()) {

      unsigned DefReg = MI->getOperand(0).getReg();
      unsigned SrcReg = MI->getOperand(1).getReg();

      if ((SrcReg == AArch64::XZR || SrcReg == AArch64::WZR) &&
          !MRI->isReserved(DefReg) &&
          (TargetReg == DefReg || TRI->isSuperRegister(DefReg, TargetReg))) {
        DEBUG(dbgs() << "Remove redundant Copy : ");
        DEBUG((MI)->print(dbgs()));

        MI->eraseFromParent();
        Changed = true;
        LastChange = I;
        NumCopiesRemoved++;
        SmallestDef =
            TRI->isSubRegister(SmallestDef, DefReg) ? DefReg : SmallestDef;
        continue;
      }
    }

    if (MI->modifiesRegister(TargetReg, TRI))
      break;
  }

  if (!Changed)
    return false;

  // Otherwise, we have to fixup the use-def chain, starting with the
  // CBZ/CBNZ. Conservatively mark as much as we can live.
  CompBr->clearRegisterKills(SmallestDef, TRI);

  if (none_of(TargetRegs, [&](unsigned Reg) { return MBB->isLiveIn(Reg); }))
    MBB->addLiveIn(TargetReg);

  // Clear any kills of TargetReg between CompBr and the last removed COPY.
  for (MachineInstr &MMI : make_range(MBB->begin(), LastChange))
    MMI.clearRegisterKills(SmallestDef, TRI);

  return true;
}

bool AArch64RedundantCopyElimination::runOnMachineFunction(
    MachineFunction &MF) {
  if (skipFunction(*MF.getFunction()))
    return false;
  TRI = MF.getSubtarget().getRegisterInfo();
  MRI = &MF.getRegInfo();
  bool Changed = false;
  for (MachineBasicBlock &MBB : MF)
    Changed |= optimizeCopy(&MBB);
  return Changed;
}

FunctionPass *llvm::createAArch64RedundantCopyEliminationPass() {
  return new AArch64RedundantCopyElimination();
}
<commit_msg>[AArch64] Minor code refactoring. NFC.<commit_after>//=- AArch64RedundantCopyElimination.cpp - Remove useless copy for AArch64 -=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
// This pass removes unnecessary zero copies in BBs that are targets of
// cbz/cbnz instructions. For instance, the copy instruction in the code below
// can be removed because the CBZW jumps to BB#2 when W0 is zero.
//  BB#1:
//    CBZW %W0, <BB#2>
//  BB#2:
//    %W0 = COPY %WZR
// This pass should be run after register allocation.
//
// FIXME: This should be extended to handle any constant other than zero. E.g.,
//   cmp w0, #1
//     b.eq .BB1
//   BB1:
//     mov w0, #1
//
// FIXME: This could also be extended to check the whole dominance subtree below
// the comparison if the compile time regression is acceptable.
//
//===----------------------------------------------------------------------===//

#include "AArch64.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

#define DEBUG_TYPE "aarch64-copyelim"

STATISTIC(NumCopiesRemoved, "Number of copies removed.");

namespace {
class AArch64RedundantCopyElimination : public MachineFunctionPass {
  const MachineRegisterInfo *MRI;
  const TargetRegisterInfo *TRI;

public:
  static char ID;
  AArch64RedundantCopyElimination() : MachineFunctionPass(ID) {
    initializeAArch64RedundantCopyEliminationPass(
        *PassRegistry::getPassRegistry());
  }
  bool optimizeCopy(MachineBasicBlock *MBB);
  bool runOnMachineFunction(MachineFunction &MF) override;
  MachineFunctionProperties getRequiredProperties() const override {
    return MachineFunctionProperties().set(
        MachineFunctionProperties::Property::NoVRegs);
  }
  StringRef getPassName() const override {
    return "AArch64 Redundant Copy Elimination";
  }
};
char AArch64RedundantCopyElimination::ID = 0;
}

INITIALIZE_PASS(AArch64RedundantCopyElimination, "aarch64-copyelim",
                "AArch64 redundant copy elimination pass", false, false)

static bool guaranteesZeroRegInBlock(MachineInstr &MI, MachineBasicBlock *MBB) {
  unsigned Opc = MI.getOpcode();
  // Check if the current basic block is the target block to which the
  // CBZ/CBNZ instruction jumps when its Wt/Xt is zero.
  return ((Opc == AArch64::CBZW || Opc == AArch64::CBZX) &&
          MBB == MI.getOperand(1).getMBB()) ||
         ((Opc == AArch64::CBNZW || Opc == AArch64::CBNZX) &&
          MBB != MI.getOperand(1).getMBB());
}

bool AArch64RedundantCopyElimination::optimizeCopy(MachineBasicBlock *MBB) {
  // Check if the current basic block has a single predecessor.
  if (MBB->pred_size() != 1)
    return false;

  // Check if the predecessor has two successors, implying the block ends in a
  // conditional branch.
  MachineBasicBlock *PredMBB = *MBB->pred_begin();
  if (PredMBB->succ_size() != 2)
    return false;

  MachineBasicBlock::iterator CompBr = PredMBB->getLastNonDebugInstr();
  if (CompBr == PredMBB->end())
    return false;

  ++CompBr;
  do {
    --CompBr;
    if (guaranteesZeroRegInBlock(*CompBr, MBB))
      break;
  } while (CompBr != PredMBB->begin() && CompBr->isTerminator());

  // We've not found a CBZ/CBNZ, time to bail out.
  if (!guaranteesZeroRegInBlock(*CompBr, MBB))
    return false;

  unsigned TargetReg = CompBr->getOperand(0).getReg();
  if (!TargetReg)
    return false;
  assert(TargetRegisterInfo::isPhysicalRegister(TargetReg) &&
         "Expect physical register");

  // Remember all registers aliasing with TargetReg.
  SmallSetVector<unsigned, 8> TargetRegs;
  for (MCRegAliasIterator AI(TargetReg, TRI, true); AI.isValid(); ++AI)
    TargetRegs.insert(*AI);

  bool Changed = false;
  MachineBasicBlock::iterator LastChange = MBB->begin();
  unsigned SmallestDef = TargetReg;
  // Remove redundant Copy instructions unless TargetReg is modified.
  for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;) {
    MachineInstr *MI = &*I;
    ++I;
    if (MI->isCopy() && MI->getOperand(0).isReg() &&
        MI->getOperand(1).isReg()) {

      unsigned DefReg = MI->getOperand(0).getReg();
      unsigned SrcReg = MI->getOperand(1).getReg();

      if ((SrcReg == AArch64::XZR || SrcReg == AArch64::WZR) &&
          !MRI->isReserved(DefReg) &&
          (TargetReg == DefReg || TRI->isSuperRegister(DefReg, TargetReg))) {
        DEBUG(dbgs() << "Remove redundant Copy : ");
        DEBUG((MI)->print(dbgs()));

        MI->eraseFromParent();
        Changed = true;
        LastChange = I;
        NumCopiesRemoved++;
        SmallestDef =
            TRI->isSubRegister(SmallestDef, DefReg) ? DefReg : SmallestDef;
        continue;
      }
    }

    if (MI->modifiesRegister(TargetReg, TRI))
      break;
  }

  if (!Changed)
    return false;

  // Otherwise, we have to fixup the use-def chain, starting with the
  // CBZ/CBNZ. Conservatively mark as much as we can live.
  CompBr->clearRegisterKills(SmallestDef, TRI);

  if (none_of(TargetRegs, [&](unsigned Reg) { return MBB->isLiveIn(Reg); }))
    MBB->addLiveIn(TargetReg);

  // Clear any kills of TargetReg between CompBr and the last removed COPY.
  for (MachineInstr &MMI : make_range(MBB->begin(), LastChange))
    MMI.clearRegisterKills(SmallestDef, TRI);

  return true;
}

bool AArch64RedundantCopyElimination::runOnMachineFunction(
    MachineFunction &MF) {
  if (skipFunction(*MF.getFunction()))
    return false;
  TRI = MF.getSubtarget().getRegisterInfo();
  MRI = &MF.getRegInfo();
  bool Changed = false;
  for (MachineBasicBlock &MBB : MF)
    Changed |= optimizeCopy(&MBB);
  return Changed;
}

FunctionPass *llvm::createAArch64RedundantCopyEliminationPass() {
  return new AArch64RedundantCopyElimination();
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
#define MAPNIK_FEATURE_STYLE_PROCESSOR_HPP

// mapnik
#include <mapnik/datasource.hpp> // for featureset_ptr

// stl
#include <set>
#include <string>
#include <vector>

namespace mapnik
{

class Map;
class layer;
class projection;
class proj_transform;
class feature_type_style;

enum eAttributeCollectionPolicy
{
    DEFAULT = 0,
    COLLECT_ALL = 1
};

template <typename Processor>
class feature_style_processor
{
    struct symbol_dispatch;
public:
    explicit feature_style_processor(Map const& m, double scale_factor = 1.0);

    /*!
     * \brief apply renderer to all map layers.
     */
    void apply();

    /*!
     * \brief apply renderer to a single layer, providing pre-populated set of query attribute names.
     */
    void apply(mapnik::layer const& lyr, std::set<std::string>& names);
private:
    /*!
     * \brief render a layer given a projection and scale.
     */
    void apply_to_layer(layer const& lay,
                        Processor & p,
                        projection const& proj0,
                        double scale_denom,
                        std::set<std::string>& names);

    /*!
     * \brief renders a featureset with the given styles.
     */
    void render_style(layer const& lay,
                      Processor & p,
                      feature_type_style* style,
                      std::string const& style_name,
                      featureset_ptr features,
                      proj_transform const& prj_trans,
                      double scale_denom);

    Map const& m_;
    double scale_factor_;
};
}

#endif // MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
<commit_msg>make apply_to_layer public<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
#define MAPNIK_FEATURE_STYLE_PROCESSOR_HPP

// mapnik
#include <mapnik/datasource.hpp> // for featureset_ptr

// stl
#include <set>
#include <string>
#include <vector>

namespace mapnik
{

class Map;
class layer;
class projection;
class proj_transform;
class feature_type_style;

enum eAttributeCollectionPolicy
{
    DEFAULT = 0,
    COLLECT_ALL = 1
};

template <typename Processor>
class feature_style_processor
{
    struct symbol_dispatch;
public:
    explicit feature_style_processor(Map const& m, double scale_factor = 1.0);

    /*!
     * \brief apply renderer to all map layers.
     */
    void apply();

    /*!
     * \brief apply renderer to a single layer, providing pre-populated set of query attribute names.
     */
    void apply(mapnik::layer const& lyr, std::set<std::string>& names);
    /*!
     * \brief render a layer given a projection and scale.
     */
    void apply_to_layer(layer const& lay,
                        Processor & p,
                        projection const& proj0,
                        double scale_denom,
                        std::set<std::string>& names);

private:
    /*!
     * \brief renders a featureset with the given styles.
     */
    void render_style(layer const& lay,
                      Processor & p,
                      feature_type_style* style,
                      std::string const& style_name,
                      featureset_ptr features,
                      proj_transform const& prj_trans,
                      double scale_denom);

    Map const& m_;
    double scale_factor_;
};
}

#endif // MAPNIK_FEATURE_STYLE_PROCESSOR_HPP
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2015-2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <modules/vectorfieldvisualizationgl/vectorfieldvisualizationglmodule.h>
#include <modules/opengl/shader/shadermanager.h>

#include <modules/vectorfieldvisualizationgl/processors/datageneration/lorenzsystem.h>
#include <modules/vectorfieldvisualizationgl/processors/datageneration/vectorfieldgenerator2d.h>
#include <modules/vectorfieldvisualizationgl/processors/datageneration/vectorfieldgenerator3d.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/lic2d.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/hedgehog2d.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/vector2dmagnitude.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/vector2dcurl.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/vector2ddivergence.h>

#include <modules/vectorfieldvisualizationgl/processors/3d/vector3dcurl.h>
#include <modules/vectorfieldvisualizationgl/processors/3d/vector3ddivergence.h>
#include <modules/vectorfieldvisualizationgl/processors/4d/tmip.h>

// Autogenerated
#include <modules/vectorfieldvisualizationgl/shader_resources.h>
#include <modules/vectorfieldvisualizationgl/processors/datageneration/vectorfieldgenerator4d.h>

namespace inviwo {

VectorFieldVisualizationGLModule::VectorFieldVisualizationGLModule(InviwoApplication* app)
    : InviwoModule(app, "VectorFieldVisualizationGL") {
    // Add a directory to the search path of the Shadermanager

    vectorfieldvisualizationgl::addShaderResources(ShaderManager::getPtr(),
                                                   {getPath(ModulePath::GLSL)});

    registerProcessor<LorenzSystem>();
    registerProcessor<VectorFieldGenerator2D>();
    registerProcessor<VectorFieldGenerator3D>();
    registerProcessor<LIC2D>();
    registerProcessor<HedgeHog2D>();

    registerProcessor<Vector2DMagnitude>();
    registerProcessor<Vector2DCurl>();
    registerProcessor<Vector2DDivergence>();

    registerProcessor<Vector3DCurl>();
    registerProcessor<Vector3DDivergence>();
    registerProcessor<TMIP>();
    registerProcessor<VectorFieldGenerator4D>();
}

int VectorFieldVisualizationGLModule::getVersion() const { return 1; }

std::unique_ptr<VersionConverter> VectorFieldVisualizationGLModule::getConverter(int version) const {
    return util::make_unique<Converter>(version);
}

VectorFieldVisualizationGLModule::Converter::Converter(int version) : version_(version) {}

bool VectorFieldVisualizationGLModule::Converter::convert(TxElement* root) {
    std::vector<xml::IdentifierReplacement> repl = {};

    const std::vector<std::pair<std::string, std::string>> volumeGLrepl = {
    {"Vector3DCurl", "vector3dcurl.frag"},
    {"Vector3DDivergence", "vector3ddivergence.frag"}};
    for (const auto& i : volumeGLrepl) {
        xml::IdentifierReplacement inport = { {xml::Kind::processor("org.inviwo." + i.first),
                                              xml::Kind::inport("org.inviwo.VolumeInport")},
                                             i.second + "inport",
                                             "inputVolume" };
        xml::IdentifierReplacement outport = { {xml::Kind::processor("org.inviwo." + i.first),
                                               xml::Kind::outport("org.inviwo.VolumeOutport")},
                                              i.second + "outport",
                                              "outputVolume" };
        repl.push_back(inport);
        repl.push_back(outport);
    }

    bool res = false;
    switch (version_) {
        case 0: {
            res |= xml::changeIdentifiers(root, repl);
        }
                return res;

        default:
            return false;  // No changes
    }
    return true;
}

}  // namespace
<commit_msg>VectorVis: Moved include<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2015-2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <modules/vectorfieldvisualizationgl/vectorfieldvisualizationglmodule.h>
#include <modules/opengl/shader/shadermanager.h>

#include <modules/vectorfieldvisualizationgl/processors/datageneration/lorenzsystem.h>
#include <modules/vectorfieldvisualizationgl/processors/datageneration/vectorfieldgenerator2d.h>
#include <modules/vectorfieldvisualizationgl/processors/datageneration/vectorfieldgenerator3d.h>
#include <modules/vectorfieldvisualizationgl/processors/datageneration/vectorfieldgenerator4d.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/lic2d.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/hedgehog2d.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/vector2dmagnitude.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/vector2dcurl.h>
#include <modules/vectorfieldvisualizationgl/processors/2d/vector2ddivergence.h>

#include <modules/vectorfieldvisualizationgl/processors/3d/vector3dcurl.h>
#include <modules/vectorfieldvisualizationgl/processors/3d/vector3ddivergence.h>
#include <modules/vectorfieldvisualizationgl/processors/4d/tmip.h>

// Autogenerated
#include <modules/vectorfieldvisualizationgl/shader_resources.h>

namespace inviwo {

VectorFieldVisualizationGLModule::VectorFieldVisualizationGLModule(InviwoApplication* app)
    : InviwoModule(app, "VectorFieldVisualizationGL") {
    // Add a directory to the search path of the Shadermanager

    vectorfieldvisualizationgl::addShaderResources(ShaderManager::getPtr(),
                                                   {getPath(ModulePath::GLSL)});

    registerProcessor<LorenzSystem>();
    registerProcessor<VectorFieldGenerator2D>();
    registerProcessor<VectorFieldGenerator3D>();
    registerProcessor<LIC2D>();
    registerProcessor<HedgeHog2D>();

    registerProcessor<Vector2DMagnitude>();
    registerProcessor<Vector2DCurl>();
    registerProcessor<Vector2DDivergence>();

    registerProcessor<Vector3DCurl>();
    registerProcessor<Vector3DDivergence>();
    registerProcessor<TMIP>();
    registerProcessor<VectorFieldGenerator4D>();
}

int VectorFieldVisualizationGLModule::getVersion() const { return 1; }

std::unique_ptr<VersionConverter> VectorFieldVisualizationGLModule::getConverter(int version) const {
    return util::make_unique<Converter>(version);
}

VectorFieldVisualizationGLModule::Converter::Converter(int version) : version_(version) {}

bool VectorFieldVisualizationGLModule::Converter::convert(TxElement* root) {
    std::vector<xml::IdentifierReplacement> repl = {};

    const std::vector<std::pair<std::string, std::string>> volumeGLrepl = {
    {"Vector3DCurl", "vector3dcurl.frag"},
    {"Vector3DDivergence", "vector3ddivergence.frag"}};
    for (const auto& i : volumeGLrepl) {
        xml::IdentifierReplacement inport = { {xml::Kind::processor("org.inviwo." + i.first),
                                              xml::Kind::inport("org.inviwo.VolumeInport")},
                                             i.second + "inport",
                                             "inputVolume" };
        xml::IdentifierReplacement outport = { {xml::Kind::processor("org.inviwo." + i.first),
                                               xml::Kind::outport("org.inviwo.VolumeOutport")},
                                              i.second + "outport",
                                              "outputVolume" };
        repl.push_back(inport);
        repl.push_back(outport);
    }

    bool res = false;
    switch (version_) {
        case 0: {
            res |= xml::changeIdentifiers(root, repl);
        }
                return res;

        default:
            return false;  // No changes
    }
    return true;
}

}  // namespace
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/media/mock_peer_connection_impl.h"

#include <vector>

#include "base/logging.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"

using testing::_;
using webrtc::AudioTrackInterface;
using webrtc::CreateSessionDescriptionObserver;
using webrtc::DtmfSenderInterface;
using webrtc::DtmfSenderObserverInterface;
using webrtc::IceCandidateInterface;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaStreamInterface;
using webrtc::PeerConnectionInterface;
using webrtc::SessionDescriptionInterface;
using webrtc::SetSessionDescriptionObserver;

namespace content {

class MockStreamCollection : public webrtc::StreamCollectionInterface {
 public:
  virtual size_t count() OVERRIDE {
    return streams_.size();
  }
  virtual MediaStreamInterface* at(size_t index) OVERRIDE {
    return streams_[index];
  }
  virtual MediaStreamInterface* find(const std::string& label) OVERRIDE {
    for (size_t i = 0; i < streams_.size(); ++i) {
      if (streams_[i]->label() == label)
        return streams_[i];
    }
    return NULL;
  }
  virtual webrtc::MediaStreamTrackInterface* FindAudioTrack(
      const std::string& id) OVERRIDE {
    for (size_t i = 0; i < streams_.size(); ++i) {
      webrtc::MediaStreamTrackInterface* track =
          streams_.at(i)->FindAudioTrack(id);
      if (track)
        return track;
    }
    return NULL;
  }
  virtual webrtc::MediaStreamTrackInterface* FindVideoTrack(
      const std::string& id) OVERRIDE {
    for (size_t i = 0; i < streams_.size(); ++i) {
      webrtc::MediaStreamTrackInterface* track =
          streams_.at(i)->FindVideoTrack(id);
      if (track)
        return track;
    }
    return NULL;
  }
  void AddStream(MediaStreamInterface* stream) {
    streams_.push_back(stream);
  }
  void RemoveStream(MediaStreamInterface* stream) {
    StreamVector::iterator it = streams_.begin();
    for (; it != streams_.end(); ++it) {
      if (it->get() == stream) {
        streams_.erase(it);
        break;
      }
    }
  }

 protected:
  virtual ~MockStreamCollection() {}

 private:
  typedef std::vector<talk_base::scoped_refptr<MediaStreamInterface> >
      StreamVector;
  StreamVector streams_;
};

class MockDataChannel : public webrtc::DataChannelInterface {
 public:
  MockDataChannel(const std::string& label,
                  const webrtc::DataChannelInit* config)
      : label_(label),
        reliable_(config->reliable),
        state_(webrtc::DataChannelInterface::kConnecting),
        config_(*config) {
  }

  virtual void RegisterObserver(
      webrtc::DataChannelObserver* observer) OVERRIDE {
  }

  virtual void UnregisterObserver() OVERRIDE {
  }

  virtual std::string label() const OVERRIDE {
    return label_;
  }

  virtual bool reliable() const OVERRIDE {
    return reliable_;
  }

  virtual bool ordered() const OVERRIDE {
    return config_.ordered;
  }

  virtual unsigned short maxRetransmitTime() const OVERRIDE {
    return config_.maxRetransmitTime;
  }

  virtual unsigned short maxRetransmits() const OVERRIDE {
    return config_.maxRetransmits;
  }

  virtual std::string protocol() const OVERRIDE {
    return config_.protocol;
  }

  virtual bool negotiated() const OVERRIDE {
    return config_.negotiated;
  }

  virtual int id() const OVERRIDE {
    NOTIMPLEMENTED();
    return 0;
  }

  virtual DataState state() const OVERRIDE {
    return state_;
  }

  virtual uint64 buffered_amount() const OVERRIDE {
    NOTIMPLEMENTED();
    return 0;
  }

  virtual void Close() OVERRIDE {
    state_ = webrtc::DataChannelInterface::kClosing;
  }

  virtual bool Send(const webrtc::DataBuffer& buffer) OVERRIDE {
    return state_ == webrtc::DataChannelInterface::kOpen;
  }

 protected:
  virtual ~MockDataChannel() {}

 private:
  std::string label_;
  bool reliable_;
  webrtc::DataChannelInterface::DataState state_;
  webrtc::DataChannelInit config_;
};

class MockDtmfSender : public DtmfSenderInterface {
 public:
  explicit MockDtmfSender(AudioTrackInterface* track)
      : track_(track),
        observer_(NULL),
        duration_(0),
        inter_tone_gap_(0) {}
  virtual void RegisterObserver(
      DtmfSenderObserverInterface* observer) OVERRIDE {
    observer_ = observer;
  }
  virtual void UnregisterObserver() OVERRIDE {
    observer_ = NULL;
  }
  virtual bool CanInsertDtmf() OVERRIDE {
    return true;
  }
  virtual bool InsertDtmf(const std::string& tones, int duration,
                          int inter_tone_gap) OVERRIDE {
    tones_ = tones;
    duration_ = duration;
    inter_tone_gap_ = inter_tone_gap;
    return true;
  }
  virtual const AudioTrackInterface* track() const OVERRIDE {
    return track_.get();
  }
  virtual std::string tones() const OVERRIDE {
    return tones_;
  }
  virtual int duration() const OVERRIDE { return duration_; }
  virtual int inter_tone_gap() const OVERRIDE { return inter_tone_gap_; }

 protected:
  virtual ~MockDtmfSender() {}

 private:
  talk_base::scoped_refptr<AudioTrackInterface> track_;
  DtmfSenderObserverInterface* observer_;
  std::string tones_;
  int duration_;
  int inter_tone_gap_;
};

const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer";
const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer";

MockPeerConnectionImpl::MockPeerConnectionImpl(
    MockPeerConnectionDependencyFactory* factory)
    : dependency_factory_(factory),
      local_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
      remote_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
      hint_audio_(false),
      hint_video_(false),
      getstats_result_(true),
      sdp_mline_index_(-1) {
  ON_CALL(*this, SetLocalDescription(_, _)).WillByDefault(testing::Invoke(
      this, &MockPeerConnectionImpl::SetLocalDescriptionWorker));
  ON_CALL(*this, SetRemoteDescription(_, _)).WillByDefault(testing::Invoke(
      this, &MockPeerConnectionImpl::SetRemoteDescriptionWorker));
}

MockPeerConnectionImpl::~MockPeerConnectionImpl() {}

talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
MockPeerConnectionImpl::local_streams() {
  return local_streams_;
}

talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
MockPeerConnectionImpl::remote_streams() {
  return remote_streams_;
}

bool MockPeerConnectionImpl::AddStream(
    MediaStreamInterface* local_stream,
    const MediaConstraintsInterface* constraints) {
  DCHECK(stream_label_.empty());
  stream_label_ = local_stream->label();
  local_streams_->AddStream(local_stream);
  return true;
}

void MockPeerConnectionImpl::RemoveStream(
    MediaStreamInterface* local_stream) {
  DCHECK_EQ(stream_label_, local_stream->label());
  stream_label_.clear();
  local_streams_->RemoveStream(local_stream);
}

talk_base::scoped_refptr<DtmfSenderInterface>
MockPeerConnectionImpl::CreateDtmfSender(AudioTrackInterface* track) {
  if (!track) {
    return NULL;
  }
  return new talk_base::RefCountedObject<MockDtmfSender>(track);
}

talk_base::scoped_refptr<webrtc::DataChannelInterface>
MockPeerConnectionImpl::CreateDataChannel(const std::string& label,
                      const webrtc::DataChannelInit* config) {
  return new talk_base::RefCountedObject<MockDataChannel>(label, config);
}

bool MockPeerConnectionImpl::GetStats(
    webrtc::StatsObserver* observer,
    webrtc::MediaStreamTrackInterface* track,
    StatsOutputLevel level) {
  if (!getstats_result_)
    return false;

  DCHECK_EQ(kStatsOutputLevelStandard, level);
  std::vector<webrtc::StatsReport> reports(track ? 1 : 2);
  webrtc::StatsReport& report = reports[0];
  report.id = "1234";
  report.type = "ssrc";
  report.timestamp = 42;
  webrtc::StatsReport::Value value;
  value.name = "trackname";
  value.value = "trackvalue";
  report.values.push_back(value);
  // If selector is given, we pass back one report.
  // If selector is not given, we pass back two.
  if (!track) {
    webrtc::StatsReport& report2 = reports[1];
    report2.id = "nontrack";
    report2.type = "generic";
    report2.timestamp = 44;
    report2.values.push_back(value);
    value.name = "somename";
    value.value = "somevalue";
    report2.values.push_back(value);
  }
  // Note that the callback is synchronous, not asynchronous; it will
  // happen before the request call completes.
  observer->OnComplete(reports);
  return true;
}

const webrtc::SessionDescriptionInterface*
MockPeerConnectionImpl::local_description() const {
  return local_desc_.get();
}

const webrtc::SessionDescriptionInterface*
MockPeerConnectionImpl::remote_description() const {
  return remote_desc_.get();
}

void MockPeerConnectionImpl::AddRemoteStream(MediaStreamInterface* stream) {
  remote_streams_->AddStream(stream);
}

void MockPeerConnectionImpl::CreateOffer(
    CreateSessionDescriptionObserver* observer,
    const MediaConstraintsInterface* constraints) {
  DCHECK(observer);
  created_sessiondescription_.reset(
      dependency_factory_->CreateSessionDescription("unknown", kDummyOffer,
                                                    NULL));
}

void MockPeerConnectionImpl::CreateAnswer(
    CreateSessionDescriptionObserver* observer,
    const MediaConstraintsInterface* constraints) {
  DCHECK(observer);
  created_sessiondescription_.reset(
      dependency_factory_->CreateSessionDescription("unknown", kDummyAnswer,
                                                    NULL));
}

void MockPeerConnectionImpl::SetLocalDescriptionWorker(
    SetSessionDescriptionObserver* observer,
    SessionDescriptionInterface* desc) {
  desc->ToString(&description_sdp_);
  local_desc_.reset(desc);
}

void MockPeerConnectionImpl::SetRemoteDescriptionWorker(
    SetSessionDescriptionObserver* observer,
    SessionDescriptionInterface* desc) {
  desc->ToString(&description_sdp_);
  remote_desc_.reset(desc);
}

bool MockPeerConnectionImpl::UpdateIce(
    const IceServers& configuration,
    const MediaConstraintsInterface* constraints) {
  return true;
}

bool MockPeerConnectionImpl::AddIceCandidate(
    const IceCandidateInterface* candidate) {
  sdp_mid_ = candidate->sdp_mid();
  sdp_mline_index_ = candidate->sdp_mline_index();
  return candidate->ToString(&ice_sdp_);
}

void MockPeerConnectionImpl::RegisterUMAObserver(
    webrtc::UMAObserver* observer) {
  NOTIMPLEMENTED();
}

}  // namespace content
<commit_msg>Fix an issue with an upcoming webrtc roll where the 'name' property of StatsReport::Value is const.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/media/mock_peer_connection_impl.h"

#include <vector>

#include "base/logging.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"

using testing::_;
using webrtc::AudioTrackInterface;
using webrtc::CreateSessionDescriptionObserver;
using webrtc::DtmfSenderInterface;
using webrtc::DtmfSenderObserverInterface;
using webrtc::IceCandidateInterface;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaStreamInterface;
using webrtc::PeerConnectionInterface;
using webrtc::SessionDescriptionInterface;
using webrtc::SetSessionDescriptionObserver;

namespace content {

class MockStreamCollection : public webrtc::StreamCollectionInterface {
 public:
  virtual size_t count() OVERRIDE {
    return streams_.size();
  }
  virtual MediaStreamInterface* at(size_t index) OVERRIDE {
    return streams_[index];
  }
  virtual MediaStreamInterface* find(const std::string& label) OVERRIDE {
    for (size_t i = 0; i < streams_.size(); ++i) {
      if (streams_[i]->label() == label)
        return streams_[i];
    }
    return NULL;
  }
  virtual webrtc::MediaStreamTrackInterface* FindAudioTrack(
      const std::string& id) OVERRIDE {
    for (size_t i = 0; i < streams_.size(); ++i) {
      webrtc::MediaStreamTrackInterface* track =
          streams_.at(i)->FindAudioTrack(id);
      if (track)
        return track;
    }
    return NULL;
  }
  virtual webrtc::MediaStreamTrackInterface* FindVideoTrack(
      const std::string& id) OVERRIDE {
    for (size_t i = 0; i < streams_.size(); ++i) {
      webrtc::MediaStreamTrackInterface* track =
          streams_.at(i)->FindVideoTrack(id);
      if (track)
        return track;
    }
    return NULL;
  }
  void AddStream(MediaStreamInterface* stream) {
    streams_.push_back(stream);
  }
  void RemoveStream(MediaStreamInterface* stream) {
    StreamVector::iterator it = streams_.begin();
    for (; it != streams_.end(); ++it) {
      if (it->get() == stream) {
        streams_.erase(it);
        break;
      }
    }
  }

 protected:
  virtual ~MockStreamCollection() {}

 private:
  typedef std::vector<talk_base::scoped_refptr<MediaStreamInterface> >
      StreamVector;
  StreamVector streams_;
};

class MockDataChannel : public webrtc::DataChannelInterface {
 public:
  MockDataChannel(const std::string& label,
                  const webrtc::DataChannelInit* config)
      : label_(label),
        reliable_(config->reliable),
        state_(webrtc::DataChannelInterface::kConnecting),
        config_(*config) {
  }

  virtual void RegisterObserver(
      webrtc::DataChannelObserver* observer) OVERRIDE {
  }

  virtual void UnregisterObserver() OVERRIDE {
  }

  virtual std::string label() const OVERRIDE {
    return label_;
  }

  virtual bool reliable() const OVERRIDE {
    return reliable_;
  }

  virtual bool ordered() const OVERRIDE {
    return config_.ordered;
  }

  virtual unsigned short maxRetransmitTime() const OVERRIDE {
    return config_.maxRetransmitTime;
  }

  virtual unsigned short maxRetransmits() const OVERRIDE {
    return config_.maxRetransmits;
  }

  virtual std::string protocol() const OVERRIDE {
    return config_.protocol;
  }

  virtual bool negotiated() const OVERRIDE {
    return config_.negotiated;
  }

  virtual int id() const OVERRIDE {
    NOTIMPLEMENTED();
    return 0;
  }

  virtual DataState state() const OVERRIDE {
    return state_;
  }

  virtual uint64 buffered_amount() const OVERRIDE {
    NOTIMPLEMENTED();
    return 0;
  }

  virtual void Close() OVERRIDE {
    state_ = webrtc::DataChannelInterface::kClosing;
  }

  virtual bool Send(const webrtc::DataBuffer& buffer) OVERRIDE {
    return state_ == webrtc::DataChannelInterface::kOpen;
  }

 protected:
  virtual ~MockDataChannel() {}

 private:
  std::string label_;
  bool reliable_;
  webrtc::DataChannelInterface::DataState state_;
  webrtc::DataChannelInit config_;
};

class MockDtmfSender : public DtmfSenderInterface {
 public:
  explicit MockDtmfSender(AudioTrackInterface* track)
      : track_(track),
        observer_(NULL),
        duration_(0),
        inter_tone_gap_(0) {}
  virtual void RegisterObserver(
      DtmfSenderObserverInterface* observer) OVERRIDE {
    observer_ = observer;
  }
  virtual void UnregisterObserver() OVERRIDE {
    observer_ = NULL;
  }
  virtual bool CanInsertDtmf() OVERRIDE {
    return true;
  }
  virtual bool InsertDtmf(const std::string& tones, int duration,
                          int inter_tone_gap) OVERRIDE {
    tones_ = tones;
    duration_ = duration;
    inter_tone_gap_ = inter_tone_gap;
    return true;
  }
  virtual const AudioTrackInterface* track() const OVERRIDE {
    return track_.get();
  }
  virtual std::string tones() const OVERRIDE {
    return tones_;
  }
  virtual int duration() const OVERRIDE { return duration_; }
  virtual int inter_tone_gap() const OVERRIDE { return inter_tone_gap_; }

 protected:
  virtual ~MockDtmfSender() {}

 private:
  talk_base::scoped_refptr<AudioTrackInterface> track_;
  DtmfSenderObserverInterface* observer_;
  std::string tones_;
  int duration_;
  int inter_tone_gap_;
};

const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer";
const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer";

MockPeerConnectionImpl::MockPeerConnectionImpl(
    MockPeerConnectionDependencyFactory* factory)
    : dependency_factory_(factory),
      local_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
      remote_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
      hint_audio_(false),
      hint_video_(false),
      getstats_result_(true),
      sdp_mline_index_(-1) {
  ON_CALL(*this, SetLocalDescription(_, _)).WillByDefault(testing::Invoke(
      this, &MockPeerConnectionImpl::SetLocalDescriptionWorker));
  ON_CALL(*this, SetRemoteDescription(_, _)).WillByDefault(testing::Invoke(
      this, &MockPeerConnectionImpl::SetRemoteDescriptionWorker));
}

MockPeerConnectionImpl::~MockPeerConnectionImpl() {}

talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
MockPeerConnectionImpl::local_streams() {
  return local_streams_;
}

talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
MockPeerConnectionImpl::remote_streams() {
  return remote_streams_;
}

bool MockPeerConnectionImpl::AddStream(
    MediaStreamInterface* local_stream,
    const MediaConstraintsInterface* constraints) {
  DCHECK(stream_label_.empty());
  stream_label_ = local_stream->label();
  local_streams_->AddStream(local_stream);
  return true;
}

void MockPeerConnectionImpl::RemoveStream(
    MediaStreamInterface* local_stream) {
  DCHECK_EQ(stream_label_, local_stream->label());
  stream_label_.clear();
  local_streams_->RemoveStream(local_stream);
}

talk_base::scoped_refptr<DtmfSenderInterface>
MockPeerConnectionImpl::CreateDtmfSender(AudioTrackInterface* track) {
  if (!track) {
    return NULL;
  }
  return new talk_base::RefCountedObject<MockDtmfSender>(track);
}

talk_base::scoped_refptr<webrtc::DataChannelInterface>
MockPeerConnectionImpl::CreateDataChannel(const std::string& label,
                      const webrtc::DataChannelInit* config) {
  return new talk_base::RefCountedObject<MockDataChannel>(label, config);
}

bool MockPeerConnectionImpl::GetStats(
    webrtc::StatsObserver* observer,
    webrtc::MediaStreamTrackInterface* track,
    StatsOutputLevel level) {
  if (!getstats_result_)
    return false;

  DCHECK_EQ(kStatsOutputLevelStandard, level);
  std::vector<webrtc::StatsReport> reports(track ? 1 : 2);
  webrtc::StatsReport& report = reports[0];
  report.id = "1234";
  report.type = "ssrc";
  report.timestamp = 42;
  webrtc::StatsReport::Value value = {
    webrtc::StatsReport::kStatsValueNameFingerprint,
    "trackvalue"
  };
  report.values.push_back(value);
  // If selector is given, we pass back one report.
  // If selector is not given, we pass back two.
  if (!track) {
    webrtc::StatsReport& report2 = reports[1];
    report2.id = "nontrack";
    report2.type = "generic";
    report2.timestamp = 44;
    report2.values.push_back(value);
    webrtc::StatsReport::Value value2 = {
      webrtc::StatsReport::kStatsValueNameFingerprintAlgorithm,
      "somevalue"
    };
    report2.values.push_back(value2);
  }
  // Note that the callback is synchronous, not asynchronous; it will
  // happen before the request call completes.
  observer->OnComplete(reports);
  return true;
}

const webrtc::SessionDescriptionInterface*
MockPeerConnectionImpl::local_description() const {
  return local_desc_.get();
}

const webrtc::SessionDescriptionInterface*
MockPeerConnectionImpl::remote_description() const {
  return remote_desc_.get();
}

void MockPeerConnectionImpl::AddRemoteStream(MediaStreamInterface* stream) {
  remote_streams_->AddStream(stream);
}

void MockPeerConnectionImpl::CreateOffer(
    CreateSessionDescriptionObserver* observer,
    const MediaConstraintsInterface* constraints) {
  DCHECK(observer);
  created_sessiondescription_.reset(
      dependency_factory_->CreateSessionDescription("unknown", kDummyOffer,
                                                    NULL));
}

void MockPeerConnectionImpl::CreateAnswer(
    CreateSessionDescriptionObserver* observer,
    const MediaConstraintsInterface* constraints) {
  DCHECK(observer);
  created_sessiondescription_.reset(
      dependency_factory_->CreateSessionDescription("unknown", kDummyAnswer,
                                                    NULL));
}

void MockPeerConnectionImpl::SetLocalDescriptionWorker(
    SetSessionDescriptionObserver* observer,
    SessionDescriptionInterface* desc) {
  desc->ToString(&description_sdp_);
  local_desc_.reset(desc);
}

void MockPeerConnectionImpl::SetRemoteDescriptionWorker(
    SetSessionDescriptionObserver* observer,
    SessionDescriptionInterface* desc) {
  desc->ToString(&description_sdp_);
  remote_desc_.reset(desc);
}

bool MockPeerConnectionImpl::UpdateIce(
    const IceServers& configuration,
    const MediaConstraintsInterface* constraints) {
  return true;
}

bool MockPeerConnectionImpl::AddIceCandidate(
    const IceCandidateInterface* candidate) {
  sdp_mid_ = candidate->sdp_mid();
  sdp_mline_index_ = candidate->sdp_mline_index();
  return candidate->ToString(&ice_sdp_);
}

void MockPeerConnectionImpl::RegisterUMAObserver(
    webrtc::UMAObserver* observer) {
  NOTIMPLEMENTED();
}

}  // namespace content
<|endoftext|>


<commit_before>//=============================================================================================================
/**
 * @file     main.cpp
 * @author   Gabriel Motta <gbmotta@mgh.harvard.edu>
 * @since    0.1.9
 * @date     September, 2021
 *
 * @section  LICENSE
 *
 * Copyright (C) 2021, Gabriel Motta. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    Average data from a raw data file
 *
 */
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <utils/files.h>

#include <chrono>
#include <string>
#include <iostream>

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QCoreApplication>
#include <QCommandLineParser>
#include <QDir>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace UTILSLIB;

//=============================================================================================================
// MAIN
//=============================================================================================================

//=============================================================================================================
/**
 * The function main marks the entry point of the program.
 * By default, main has the storage class extern.
 *
 * @param[in] argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started.
 * @param[in] argv (argument vector) is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started.
 * @return the value that was set to exit() (which is 0 if exit() is called via quit()).
 */
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // Command Line Parser
    QCommandLineParser parser;
    parser.setApplicationDescription("File Utils Example");
    parser.addHelpOption();

    QCommandLineOption stepOption("step", "Steps through each command waiting for input before proceeding.", "pickAll", "true");
    parser.addOption(stepOption);

    parser.process(a);

    bool bStep = (parser.value("step") == "true");

    std::string sDirPath = QCoreApplication::applicationDirPath().toStdString();
    std::string sFilePath = sDirPath + "/test.txt";

    std::cout << "=====  Creating File  =====\n";
    if(bStep){
        std::cout << "Press RETURN to execute.\n";
        std::cin.get();
    }
    Files::create(sFilePath);

    std::cout << "=====  Checking File  =====\n";
    if(bStep){
        std::cout << "Press RETURN to execute.\n";
        std::cin.get();
    }
    std::string answer;
    if (Files::exists(sFilePath)){
        answer = "Yes.";
    } else {
        answer = "No.";
    }
    std::cout << "Does file exist? " << answer << "\n";

    std::cout << "=====  Copying File   =====\n";
    if(bStep){
        std::cout << "Press RETURN to execute.\n";
        std::cin.get();
    }

    std::string sFilePath2 = sDirPath + "/test_copy.txt";
    std::string sFilePath3 = sDirPath + "/another_test_copy.txt";

    Files::copy(sFilePath, sFilePath2);
    Files::copy(sFilePath2, sFilePath);

    std::cout << "=====  Renaming File  =====\n";
    if(bStep){
        std::cout << "Press RETURN to execute.\n";
        std::cin.get();
    }
    std::string sFilePath4 = sDirPath + "/another_test_copy.txt";

    Files::rename(sFilePath3, sFilePath4);

    return a.exec();
}
<commit_msg>debug file utils example<commit_after>//=============================================================================================================
/**
 * @file     main.cpp
 * @author   Gabriel Motta <gbmotta@mgh.harvard.edu>
 * @since    0.1.9
 * @date     September, 2021
 *
 * @section  LICENSE
 *
 * Copyright (C) 2021, Gabriel Motta. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    Average data from a raw data file
 *
 */
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <utils/files.h>

#include <chrono>
#include <string>
#include <iostream>

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QCoreApplication>
#include <QCommandLineParser>
#include <QDir>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace UTILSLIB;

//=============================================================================================================
// MAIN
//=============================================================================================================

//=============================================================================================================
/**
 * The function main marks the entry point of the program.
 * By default, main has the storage class extern.
 *
 * @param[in] argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started.
 * @param[in] argv (argument vector) is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started.
 * @return the value that was set to exit() (which is 0 if exit() is called via quit()).
 */
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // Command Line Parser
    QCommandLineParser parser;
    parser.setApplicationDescription("File Utils Example");
    parser.addHelpOption();

    QCommandLineOption stepOption("step", "Steps through each command waiting for input before proceeding.", "pickAll", "true");
    parser.addOption(stepOption);

    parser.process(a);

    bool bStep = (parser.value("step") == "true");

    std::string sDirPath = QCoreApplication::applicationDirPath().toStdString();
    std::string sFilePath = sDirPath + "/test.txt";

    std::cout << "=====  Creating File  =====\n";
    if(bStep){
        std::cout << "Press RETURN to execute.\n";
        std::cin.get();
    }
    Files::create(sFilePath);

    std::cout << "=====  Checking File  =====\n";
    if(bStep){
        std::cout << "Press RETURN to execute.\n";
        std::cin.get();
    }
    std::string answer;
    if (Files::exists(sFilePath)){
        answer = "Yes.";
    } else {
        answer = "No.";
    }
    std::cout << "Does file exist? " << answer << "\n";

    std::cout << "=====  Copying File   =====\n";
    if(bStep){
        std::cout << "Press RETURN to execute.\n";
        std::cin.get();
    }

    std::string sFilePath2 = sDirPath + "/test_copy.txt";
    std::string sFilePath3 = sDirPath + "/another_test_copy.txt";

    Files::copy(sFilePath, sFilePath2);
    Files::copy(sFilePath2, sFilePath3);

    std::cout << "=====  Renaming File  =====\n";
    if(bStep){
        std::cout << "Press RETURN to execute.\n";
        std::cin.get();
    }
    std::string sFilePath4 = sDirPath + "/yet_another_test_copy.txt";

    Files::rename(sFilePath3, sFilePath4);

    std::cout << "=====  Removing File  =====\n";
    if(bStep){
        std::cout << "Press RETURN to execute.\n";
        std::cin.get();
    }
    Files::remove(sFilePath);
    Files::remove(sFilePath2);
    Files::remove(sFilePath4);

    return a.exec();
}
<|endoftext|>