<commit_before>#include "main_window.h"
#include "ui_main_window.h"

#include <QtGlobal>

#include <scene_detector.h>

main_window::main_window(QWidget* parent, CutDetector* detector)
    : QMainWindow(parent),
      ui(new Ui::main_window),
      comparator_options_dialog_(new ComparatorOptionsDialog(
          this,
          static_cast<HistogramBasedFrameComparator*>(
              detector->frame_comparator()))),
      scene_list_preview_dialog_(new SceneListPreviewDialog(this)) {
  detector_.reset(detector);
  detector_->scene_detector()->RegisterObserver(&interface_);
  detector_->video_reader()->RegisterObserver(&interface_);

  scene_list_preview_dialog_->setVideoReader(detector_->video_reader());

  worker_thread_.start();
  interface_.set_detector(detector_.get());
  interface_.moveToThread(&worker_thread_);

  ui->setupUi(this);

  setupSignals();
}

void main_window::setupSignals() {
  qRegisterMetaType<cv::Mat>("cv::Mat");
  qRegisterMetaType<QVector<int> >("QVector<int>");

  // Detector settings signals
  QObject::connect(ui->detectorSettingsButton, &QAbstractButton::clicked, this,
                   &main_window::openComparatorSettingsDialog);
  QObject::connect(ui->saveDetectorSettingsButton, &QAbstractButton::clicked,
                   [=]() { interface_.saveSettingsJsonFile(this); });
  QObject::connect(ui->loadDetectorSettingsButton, &QAbstractButton::clicked,
                   [=]() { interface_.openSettingsJsonFile(this); });

  // OpenCVWidget signals
  QObject::connect(&interface_, &CutDetectorQtInterface::showCurrentFrame,
                   ui->bottomOpenCVWidget, &OpenCVImageWidget::showImage);
  QObject::connect(&interface_, &CutDetectorQtInterface::showNewSceneFirstFrame,
                   ui->bottomOpenCVWidget, &OpenCVImageWidget::showImage);
  QObject::connect(&interface_,
                   &CutDetectorQtInterface::showPreviousSceneLastFrame,
                   ui->topOpenCVWidget, &OpenCVImageWidget::showImage);

  // Scene detection signals
  QObject::connect(ui->startButton, &QToolButton::clicked, &interface_,
                   &CutDetectorQtInterface::detectScenes);
  QObject::connect(&interface_, &CutDetectorQtInterface::sceneListGenerated,
                   [=](sceneList list) {
                     for (auto scene : list) {
                       QTableWidgetItem* item1 =
                           new QTableWidgetItem(QString::number(scene.first));
                       QTableWidgetItem* item2 =
                           new QTableWidgetItem(QString::number(scene.second));
                       int row = ui->sceneTableWidget->rowCount();
                       ui->sceneTableWidget->setRowCount(
                           ui->sceneTableWidget->rowCount() + 1);
                       ui->sceneTableWidget->setItem(row, 0, item1);
                       ui->sceneTableWidget->setItem(row, 1, item2);
                     }
                   });
  QObject::connect(&interface_, &CutDetectorQtInterface::sceneDetectionStarted,
                   this, &main_window::clearScenesList);

  // Video Reader controls
  QObject::connect(
      &interface_, &CutDetectorQtInterface::changeCurrentFrameIndex,
      [=](int current, int total) {
        ui->playbackSlider->setValue(((double)current / total) * 100);
      });
  QObject::connect(ui->actionOpen_file, &QAction::triggered, [=]() {
    interface_.openVideoFile(this);
    clearScenesList();
  });
  QObject::connect(ui->stepForwardButton, &QAbstractButton::clicked,
                   &interface_, &CutDetectorQtInterface::stepVideoForward);
  QObject::connect(ui->stepBackButton, &QAbstractButton::clicked, &interface_,
                   &CutDetectorQtInterface::stepVideoBackward);
  QObject::connect(ui->rewindButton, &QAbstractButton::clicked, &interface_,
                   &CutDetectorQtInterface::rewindVideo);
  QObject::connect(ui->endButton, &QAbstractButton::clicked, &interface_,
                   &CutDetectorQtInterface::fastforwardVideo);

  // Scene list controls
  QObject::connect(ui->actionClear_cuts_list, &QAction::triggered, this,
                   &main_window::clearScenesList);
  QObject::connect(ui->clearListButton, &QAbstractButton::clicked, this,
                   &main_window::clearScenesList);
  QObject::connect(ui->loadListButton, &QAbstractButton::clicked,
                   [=]() { loadSceneList(interface_.openCutsFile(this)); });
  QObject::connect(ui->saveListButton, &QAbstractButton::clicked, [=]() {
    interface_.saveCutsFile(this, generateSceneList());
  });
  QObject::connect(ui->addRowButton, &QAbstractButton::clicked, [=]() {
    int rowCount = ui->sceneTableWidget->rowCount();
    ui->sceneTableWidget->setRowCount(++rowCount);
    ui->sceneTableWidget->setCurrentCell(rowCount - 1, 0);
  });
  QObject::connect(ui->deleteRowButton, &QAbstractButton::clicked, [=]() {
    int rowCount = ui->sceneTableWidget->rowCount();
    ui->sceneTableWidget->setRowCount(--rowCount);
    ui->sceneTableWidget->setCurrentCell(rowCount - 1, 0);
  });

  // Scene list table widget
  QObject::connect(ui->sceneTableWidget, &QTableWidget::cellChanged,
                   [=](int row, int collumn) {
                     auto item = ui->sceneTableWidget->item(row, collumn);
                     if (item->text().isEmpty())
                       return;
                     int rowCount = ui->sceneTableWidget->rowCount();
                     if (rowCount <= (row + 1)) {
                       ui->sceneTableWidget->setRowCount(++rowCount);
                     }
                     int currentVal = item->text().toInt();
                     auto newItem = new QTableWidgetItem();
                     int nextRow = collumn ? row + 1 : row;
                     int nextCol = (collumn + 1) % 2;
                     int newValue = currentVal + 1;
                     if (collumn == 0) {
                       auto nextItem =
                           ui->sceneTableWidget->item(nextRow, nextCol);
                       if (!nextItem || nextItem->text().isEmpty() ||
                           nextItem->text().toInt() > newValue) {
                         ui->sceneTableWidget->setCurrentCell(nextRow, collumn);
                         return;
                       }
                     }
                     newItem->setText(QString::number(newValue));
                     ui->sceneTableWidget->setItem(nextRow, nextCol, newItem);
                     ui->sceneTableWidget->setCurrentCell(nextRow, nextCol);
                   });

  // Scene list preview dialog
  QObject::connect(ui->openSceneListPreviewButton, &QAbstractButton::clicked,
                   [=]() {
                     QList<QString> list = generateSceneList();
                     if (!list.empty()) {
                       this->scene_list_preview_dialog_->loadScenesList(list);
                       this->scene_list_preview_dialog_->show();
                     }
                   });
}

QList<QString> main_window::generateSceneList() {
  ui->sceneTableWidget->blockSignals(true);
  QList<QString> result;
  for (int i = 0; i < ui->sceneTableWidget->rowCount(); ++i) {
    QString temp = "[";
    for (int j = 0; j < ui->sceneTableWidget->columnCount(); ++j) {
      if (j != 0)
        temp += ";";

      temp += ui->sceneTableWidget->item(i, j)->text();
    }
    result.push_back(temp + "]");
  }
  ui->sceneTableWidget->blockSignals(false);
  return result;
}

void main_window::loadSceneList(QList<QString> list) {
  ui->sceneTableWidget->setRowCount(0);
  for (QString scene : list) {
    scene.remove(QChar('['));
    scene.remove(QChar(']'));
    auto cells = scene.split(";");
    int row = ui->sceneTableWidget->rowCount();
    ui->sceneTableWidget->setRowCount(row + 1);
    int col = 0;
    for (QString cell : cells) {
      auto item = new QTableWidgetItem(cell);
      ui->sceneTableWidget->setItem(row, col, item);
      ++col;
    }
  }
}

void main_window::clearScenesList() {
  ui->sceneTableWidget->setRowCount(0);
}

void main_window::openComparatorSettingsDialog() {
  comparator_options_dialog_->show();
}

main_window::~main_window() {
  worker_thread_.exit();
  worker_thread_.wait();
  delete ui;
}
<commit_msg>Fix crash on opening scene preview<commit_after>#include "main_window.h"
#include "ui_main_window.h"

#include <QtGlobal>

#include <scene_detector.h>

main_window::main_window(QWidget* parent, CutDetector* detector)
    : QMainWindow(parent),
      ui(new Ui::main_window),
      comparator_options_dialog_(new ComparatorOptionsDialog(
          this,
          static_cast<HistogramBasedFrameComparator*>(
              detector->frame_comparator()))),
      scene_list_preview_dialog_(new SceneListPreviewDialog(this)) {
  detector_.reset(detector);
  detector_->scene_detector()->RegisterObserver(&interface_);
  detector_->video_reader()->RegisterObserver(&interface_);

  scene_list_preview_dialog_->setVideoReader(detector_->video_reader());

  worker_thread_.start();
  interface_.set_detector(detector_.get());
  interface_.moveToThread(&worker_thread_);

  ui->setupUi(this);

  setupSignals();
}

void main_window::setupSignals() {
  qRegisterMetaType<cv::Mat>("cv::Mat");
  qRegisterMetaType<QVector<int> >("QVector<int>");

  // Detector settings signals
  QObject::connect(ui->detectorSettingsButton, &QAbstractButton::clicked, this,
                   &main_window::openComparatorSettingsDialog);
  QObject::connect(ui->saveDetectorSettingsButton, &QAbstractButton::clicked,
                   [=]() { interface_.saveSettingsJsonFile(this); });
  QObject::connect(ui->loadDetectorSettingsButton, &QAbstractButton::clicked,
                   [=]() { interface_.openSettingsJsonFile(this); });

  // OpenCVWidget signals
  QObject::connect(&interface_, &CutDetectorQtInterface::showCurrentFrame,
                   ui->bottomOpenCVWidget, &OpenCVImageWidget::showImage);
  QObject::connect(&interface_, &CutDetectorQtInterface::showNewSceneFirstFrame,
                   ui->bottomOpenCVWidget, &OpenCVImageWidget::showImage);
  QObject::connect(&interface_,
                   &CutDetectorQtInterface::showPreviousSceneLastFrame,
                   ui->topOpenCVWidget, &OpenCVImageWidget::showImage);

  // Scene detection signals
  QObject::connect(ui->startButton, &QToolButton::clicked, &interface_,
                   &CutDetectorQtInterface::detectScenes);
  QObject::connect(&interface_, &CutDetectorQtInterface::sceneListGenerated,
                   [=](sceneList list) {
                     for (auto scene : list) {
                       QTableWidgetItem* item1 =
                           new QTableWidgetItem(QString::number(scene.first));
                       QTableWidgetItem* item2 =
                           new QTableWidgetItem(QString::number(scene.second));
                       int row = ui->sceneTableWidget->rowCount();
                       ui->sceneTableWidget->setRowCount(
                           ui->sceneTableWidget->rowCount() + 1);
                       ui->sceneTableWidget->setItem(row, 0, item1);
                       ui->sceneTableWidget->setItem(row, 1, item2);
                     }
                   });
  QObject::connect(&interface_, &CutDetectorQtInterface::sceneDetectionStarted,
                   this, &main_window::clearScenesList);

  // Video Reader controls
  QObject::connect(
      &interface_, &CutDetectorQtInterface::changeCurrentFrameIndex,
      [=](int current, int total) {
        ui->playbackSlider->setValue(((double)current / total) * 100);
      });
  QObject::connect(ui->actionOpen_file, &QAction::triggered, [=]() {
    interface_.openVideoFile(this);
    clearScenesList();
  });
  QObject::connect(ui->stepForwardButton, &QAbstractButton::clicked,
                   &interface_, &CutDetectorQtInterface::stepVideoForward);
  QObject::connect(ui->stepBackButton, &QAbstractButton::clicked, &interface_,
                   &CutDetectorQtInterface::stepVideoBackward);
  QObject::connect(ui->rewindButton, &QAbstractButton::clicked, &interface_,
                   &CutDetectorQtInterface::rewindVideo);
  QObject::connect(ui->endButton, &QAbstractButton::clicked, &interface_,
                   &CutDetectorQtInterface::fastforwardVideo);

  // Scene list controls
  QObject::connect(ui->actionClear_cuts_list, &QAction::triggered, this,
                   &main_window::clearScenesList);
  QObject::connect(ui->clearListButton, &QAbstractButton::clicked, this,
                   &main_window::clearScenesList);
  QObject::connect(ui->loadListButton, &QAbstractButton::clicked,
                   [=]() { loadSceneList(interface_.openCutsFile(this)); });
  QObject::connect(ui->saveListButton, &QAbstractButton::clicked, [=]() {
    interface_.saveCutsFile(this, generateSceneList());
  });
  QObject::connect(ui->addRowButton, &QAbstractButton::clicked, [=]() {
    int rowCount = ui->sceneTableWidget->rowCount();
    ui->sceneTableWidget->setRowCount(++rowCount);
    ui->sceneTableWidget->setCurrentCell(rowCount - 1, 0);
  });
  QObject::connect(ui->deleteRowButton, &QAbstractButton::clicked, [=]() {
    int rowCount = ui->sceneTableWidget->rowCount();
    ui->sceneTableWidget->setRowCount(--rowCount);
    ui->sceneTableWidget->setCurrentCell(rowCount - 1, 0);
  });

  // Scene list table widget
  QObject::connect(ui->sceneTableWidget, &QTableWidget::cellChanged,
                   [=](int row, int collumn) {
                     auto item = ui->sceneTableWidget->item(row, collumn);
                     if (item->text().isEmpty())
                       return;
                     int rowCount = ui->sceneTableWidget->rowCount();
                     if (rowCount <= (row + 1)) {
                       ui->sceneTableWidget->setRowCount(++rowCount);
                     }
                     int currentVal = item->text().toInt();
                     auto newItem = new QTableWidgetItem();
                     int nextRow = collumn ? row + 1 : row;
                     int nextCol = (collumn + 1) % 2;
                     int newValue = currentVal + 1;
                     if (collumn == 0) {
                       auto nextItem =
                           ui->sceneTableWidget->item(nextRow, nextCol);
                       if (!nextItem || nextItem->text().isEmpty() ||
                           nextItem->text().toInt() > newValue) {
                         ui->sceneTableWidget->setCurrentCell(nextRow, collumn);
                         return;
                       }
                     }
                     newItem->setText(QString::number(newValue));
                     ui->sceneTableWidget->setItem(nextRow, nextCol, newItem);
                     ui->sceneTableWidget->setCurrentCell(nextRow, nextCol);
                   });

  // Scene list preview dialog
  QObject::connect(ui->openSceneListPreviewButton, &QAbstractButton::clicked,
                   [=]() {
                     QList<QString> list = generateSceneList();
                     if (!list.empty()) {
                       this->scene_list_preview_dialog_->loadScenesList(list);
                       this->scene_list_preview_dialog_->show();
                     }
                   });
}

QList<QString> main_window::generateSceneList() {
  ui->sceneTableWidget->blockSignals(true);
  QList<QString> result;
  for (int i = 0; i < ui->sceneTableWidget->rowCount(); ++i) {
    QString temp = "[";
    for (int j = 0; j < ui->sceneTableWidget->columnCount(); ++j) {
      if (j != 0)
        temp += ";";

      if (ui->sceneTableWidget->item(i, j))
        temp += ui->sceneTableWidget->item(i, j)->text();
      else
        temp.clear();
    }
    if (!temp.isEmpty())
      result.push_back(temp + "]");
  }
  ui->sceneTableWidget->blockSignals(false);
  return result;
}

void main_window::loadSceneList(QList<QString> list) {
  ui->sceneTableWidget->setRowCount(0);
  for (QString scene : list) {
    scene.remove(QChar('['));
    scene.remove(QChar(']'));
    auto cells = scene.split(";");
    int row = ui->sceneTableWidget->rowCount();
    ui->sceneTableWidget->setRowCount(row + 1);
    int col = 0;
    for (QString cell : cells) {
      auto item = new QTableWidgetItem(cell);
      ui->sceneTableWidget->setItem(row, col, item);
      ++col;
    }
  }
}

void main_window::clearScenesList() {
  ui->sceneTableWidget->setRowCount(0);
}

void main_window::openComparatorSettingsDialog() {
  comparator_options_dialog_->show();
}

main_window::~main_window() {
  worker_thread_.exit();
  worker_thread_.wait();
  delete ui;
}
<|endoftext|>


<commit_before>///
/// @file   StorePrimes.hpp
/// @brief  Store primes in a vector.
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef STOREPRIMES_HPP
#define STOREPRIMES_HPP

#include "iterator.hpp"
#include "primesieve_error.hpp"

#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <limits>
#include <string>

namespace primesieve {

/// primeCountApprox(x) >= pi(x)
inline std::size_t prime_count_approx(uint64_t start, uint64_t stop)
{
  if (start > stop)
    return 0;

  // pi(x) <= x / (log(x) - 1.1) + 5, for x >= 4.
  // Pierre Dusart, https://arxiv.org/abs/1002.0442 eq. 6.6.
  double x = (double) stop;
  x = std::max<double>(100.0, x);
  double pix = (stop - start) / (std::log(x) - 1.1) + 5;

  return (std::size_t) pix;
}

/// Used to print type name in error messages
template <typename T> inline std::string getTypeName() { return "Type"; }
template <> inline std::string getTypeName<int8_t>() { return "int8_t"; }
template <> inline std::string getTypeName<uint8_t>() { return "uint8_t"; }
template <> inline std::string getTypeName<int16_t>() { return "int16_t"; }
template <> inline std::string getTypeName<uint16_t>() { return "uint16_t"; }
template <> inline std::string getTypeName<int32_t>() { return "int32_t"; }
template <> inline std::string getTypeName<uint32_t>() { return "uint32_t"; }
template <> inline std::string getTypeName<int64_t>() { return "int64_t"; }
template <> inline std::string getTypeName<uint64_t>() { return "uint64_t"; }

template <typename T>
inline void store_primes(uint64_t start,
                         uint64_t stop,
                         T& primes)
{
#if defined(_MSC_VER)
  #pragma warning(push)
  // Disable warning: conversion from X to Y, possible loss of data
  #pragma warning(disable : 4244)
  // Disable warning C4018: '>': signed/unsigned mismatch
  #pragma warning(disable : 4018)
#endif

  if (start > stop)
    return;

  using V = typename T::value_type;
  if (stop > std::numeric_limits<V>::max())
    throw primesieve_error("store_primes(): " + getTypeName<V>() + " is too narrow for generating primes up to " + std::to_string(stop));

  std::size_t size = primes.size() + prime_count_approx(start, stop);
  primes.reserve(size);

  primesieve::iterator it(start, stop);
  it.generate_next_primes();

  uint64_t maxPrime64bits = 18446744073709551557ull;
  uint64_t limit = std::min(stop, maxPrime64bits - 1);

  for (; it.primes_[it.size_ - 1] <= limit; it.generate_next_primes())
    primes.insert(primes.end(), it.primes_, it.primes_ + it.size_);
  for (std::size_t i = 0; it.primes_[i] <= limit; i++)
    primes.push_back((V) it.primes_[i]);

  if (stop >= maxPrime64bits)
    primes.push_back((V) maxPrime64bits);

#if defined(_MSC_VER)
  #pragma warning(pop)
#endif
}

template <typename T>
inline void store_n_primes(uint64_t n,
                           uint64_t start,
                           T& primes)
{
#if defined(_MSC_VER)
  #pragma warning(push)
  // Disable warning: conversion from X to Y, possible loss of data
  #pragma warning(disable : 4244)
  // Disable warning C4018: '>': signed/unsigned mismatch
  #pragma warning(disable : 4018)
#endif

  if (n == 0)
    return;

  using V = typename T::value_type;
  std::size_t size = primes.size() + (std::size_t) n;
  primes.reserve(size);

  // nthPrime < n(log n + log log n), for n >= 6.
  // https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number
  double x = std::max<double>({6.0, (double) n, (double) start});
  double logn = std::log(x);
  double loglogn = std::log(logn);
  uint64_t nthPrime = (uint64_t)(n * (logn + loglogn));
  uint64_t stop = start + nthPrime;

  primesieve::iterator it(start, stop);
  it.generate_next_primes();

  while (n >= it.size_)
  {
    if (it.primes_[it.size_ - 1] > std::numeric_limits<V>::max())
      throw primesieve_error("store_n_primes(): " + getTypeName<V>() + " is too narrow for generating primes up to " + std::to_string(stop));

    primes.insert(primes.end(), it.primes_, it.primes_ + it.size_);
    n -= it.size_;
    if (n == 0)
      return;

    it.generate_next_primes();
  }

  if (it.primes_[n - 1] > std::numeric_limits<V>::max())
    throw primesieve_error("store_n_primes(): " + getTypeName<V>() + " is too narrow for generating primes up to " + std::to_string(stop));

  for (std::size_t i = 0; i < (std::size_t) n; i++)
    primes.push_back((V) it.primes_[i]);

#if defined(_MSC_VER)
  #pragma warning(pop)
#endif
}

} // namespace

#endif
<commit_msg>Add comment<commit_after>///
/// @file   StorePrimes.hpp
/// @brief  Store primes in a vector.
///
/// Copyright (C) 2022 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef STOREPRIMES_HPP
#define STOREPRIMES_HPP

#include "iterator.hpp"
#include "primesieve_error.hpp"

#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <limits>
#include <string>

namespace primesieve {

/// primeCountApprox(x) >= pi(x)
inline std::size_t prime_count_approx(uint64_t start, uint64_t stop)
{
  if (start > stop)
    return 0;

  // pi(x) <= x / (log(x) - 1.1) + 5, for x >= 4.
  // Pierre Dusart, https://arxiv.org/abs/1002.0442 eq. 6.6.
  double x = (double) stop;
  x = std::max<double>(100.0, x);
  double pix = (stop - start) / (std::log(x) - 1.1) + 5;

  return (std::size_t) pix;
}

/// Used to print type name in error messages
template <typename T> inline std::string getTypeName() { return "Type"; }
template <> inline std::string getTypeName<int8_t>() { return "int8_t"; }
template <> inline std::string getTypeName<uint8_t>() { return "uint8_t"; }
template <> inline std::string getTypeName<int16_t>() { return "int16_t"; }
template <> inline std::string getTypeName<uint16_t>() { return "uint16_t"; }
template <> inline std::string getTypeName<int32_t>() { return "int32_t"; }
template <> inline std::string getTypeName<uint32_t>() { return "uint32_t"; }
template <> inline std::string getTypeName<int64_t>() { return "int64_t"; }
template <> inline std::string getTypeName<uint64_t>() { return "uint64_t"; }

template <typename T>
inline void store_primes(uint64_t start,
                         uint64_t stop,
                         T& primes)
{
#if defined(_MSC_VER)
  #pragma warning(push)
  // Disable warning: conversion from X to Y, possible loss of data
  #pragma warning(disable : 4244)
  // Disable warning C4018: '>': signed/unsigned mismatch
  #pragma warning(disable : 4018)
#endif

  if (start > stop)
    return;

  using V = typename T::value_type;
  if (stop > std::numeric_limits<V>::max())
    throw primesieve_error("store_primes(): " + getTypeName<V>() + " is too narrow for generating primes up to " + std::to_string(stop));

  std::size_t size = primes.size() + prime_count_approx(start, stop);
  primes.reserve(size);

  primesieve::iterator it(start, stop);
  it.generate_next_primes();

  // primesieve::iterator throws an exception if one tries to
  // generate primes > 2^64. Hence we must avoid calling
  // generate_next_primes() after the largest 64-bit prime.
  uint64_t maxPrime64bits = 18446744073709551557ull;
  uint64_t limit = std::min(stop, maxPrime64bits - 1);

  for (; it.primes_[it.size_ - 1] <= limit; it.generate_next_primes())
    primes.insert(primes.end(), it.primes_, it.primes_ + it.size_);
  for (std::size_t i = 0; it.primes_[i] <= limit; i++)
    primes.push_back((V) it.primes_[i]);

  if (stop >= maxPrime64bits)
    primes.push_back((V) maxPrime64bits);

#if defined(_MSC_VER)
  #pragma warning(pop)
#endif
}

template <typename T>
inline void store_n_primes(uint64_t n,
                           uint64_t start,
                           T& primes)
{
#if defined(_MSC_VER)
  #pragma warning(push)
  // Disable warning: conversion from X to Y, possible loss of data
  #pragma warning(disable : 4244)
  // Disable warning C4018: '>': signed/unsigned mismatch
  #pragma warning(disable : 4018)
#endif

  if (n == 0)
    return;

  using V = typename T::value_type;
  std::size_t size = primes.size() + (std::size_t) n;
  primes.reserve(size);

  // nthPrime < n(log n + log log n), for n >= 6.
  // https://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number
  double x = std::max<double>({6.0, (double) n, (double) start});
  double logn = std::log(x);
  double loglogn = std::log(logn);
  uint64_t nthPrime = (uint64_t)(n * (logn + loglogn));
  uint64_t stop = start + nthPrime;

  primesieve::iterator it(start, stop);
  it.generate_next_primes();

  while (n >= it.size_)
  {
    if (it.primes_[it.size_ - 1] > std::numeric_limits<V>::max())
      throw primesieve_error("store_n_primes(): " + getTypeName<V>() + " is too narrow for generating primes up to " + std::to_string(stop));

    primes.insert(primes.end(), it.primes_, it.primes_ + it.size_);
    n -= it.size_;
    if (n == 0)
      return;

    it.generate_next_primes();
  }

  if (it.primes_[n - 1] > std::numeric_limits<V>::max())
    throw primesieve_error("store_n_primes(): " + getTypeName<V>() + " is too narrow for generating primes up to " + std::to_string(stop));

  for (std::size_t i = 0; i < (std::size_t) n; i++)
    primes.push_back((V) it.primes_[i]);

#if defined(_MSC_VER)
  #pragma warning(pop)
#endif
}

} // namespace

#endif
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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.
 *
 * Author: Radu Bogdan rusu, Suat Gedikli
 *
 */
// PCL
#include <Eigen/Geometry>
#include <pcl/common/common.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/pcd_grabber.h>
#include <cfloat>
#include <pcl/visualization/point_cloud_handlers.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/histogram_visualizer.h>
#include <pcl/terminal_tools/print.h>
#include <pcl/terminal_tools/parse.h>
#include <pcl/terminal_tools/time.h>

using terminal_tools::print_color;
using terminal_tools::print_error;
using terminal_tools::print_error;
using terminal_tools::print_warn;
using terminal_tools::print_info;
using terminal_tools::print_debug;
using terminal_tools::print_value;
using terminal_tools::print_highlight;
using terminal_tools::TT_BRIGHT;
using terminal_tools::TT_RED;
using terminal_tools::TT_GREEN;
using terminal_tools::TT_BLUE;

typedef pcl_visualization::PointCloudColorHandler<pcl::PointCloud<pcl::PointXYZ> > ColorHandler;
typedef ColorHandler::Ptr ColorHandlerPtr;
typedef ColorHandler::ConstPtr ColorHandlerConstPtr;

typedef pcl_visualization::PointCloudGeometryHandler<pcl::PointCloud<pcl::PointXYZ> > GeometryHandler;
typedef GeometryHandler::Ptr GeometryHandlerPtr;
typedef GeometryHandler::ConstPtr GeometryHandlerConstPtr;
boost::mutex mutex_;

#define NORMALS_SCALE 0.01
#define PC_SCALE 0.001

void
  printHelp (int argc, char **argv)
{
  //print_error ("Syntax is: %s <file_name 1..N>.pcd <options>\n", argv[0]);
  print_error ("Syntax is: %s <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -dev device_id           = device to be used\n");
  print_info ("                                                maybe \"#n\", with n being the number of the device in device list.\n");
  print_info ("                                                maybe \"bus@addr\", with bus and addr being the usb bus and address where device is connected.\n");
  print_info ("                                                maybe \"serial\", with serial being the serial number of the device.\n");
  print_info ("                     -bc r,g,b                = background color\n");
  print_info ("                     -fc r,g,b                = foreground color\n");
  print_info ("                     -ps X                    = point size ("); print_value ("1..64"); print_info (") \n");
  print_info ("                     -opaque X                = rendered point cloud opacity ("); print_value ("0..1"); print_info (")\n");

  print_info ("                     -ax "); print_value ("n"); print_info ("                    = enable on-screen display of ");
  print_color (stdout, TT_BRIGHT, TT_RED, "X"); print_color (stdout, TT_BRIGHT, TT_GREEN, "Y"); print_color (stdout, TT_BRIGHT, TT_BLUE, "Z");
  print_info (" axes and scale them to "); print_value ("n\n");
  print_info ("                     -ax_pos X,Y,Z            = if axes are enabled, set their X,Y,Z position in space (default "); print_value ("0,0,0"); print_info (")\n");

  print_info ("\n");
  print_info ("                     -cam (*)                 = use given camera settings as initial view\n");
  print_info (stderr, " (*) [Clipping Range / Focal Point / Position / ViewUp / Distance / Window Size / Window Pos] or use a <filename.cam> that contains the same information.\n");

  print_info ("\n");
  print_info ("                     -multiview 0/1           = enable/disable auto-multi viewport rendering (default "); print_value ("disabled"); print_info (")\n");
  print_info ("\n");

  print_info ("\n");
  print_info ("                     -normals 0/X             = disable/enable the display of every Xth point's surface normal as lines (default "); print_value ("disabled"); print_info (")\n");
  print_info ("                     -normals_scale X         = resize the normal unit vector size to X (default "); print_value ("0.02"); print_info (")\n");
  print_info ("\n");
  print_info ("                     -pc 0/X                  = disable/enable the display of every Xth point's principal curvatures as lines (default "); print_value ("disabled"); print_info (")\n");
  print_info ("                     -pc_scale X              = resize the principal curvatures vectors size to X (default "); print_value ("0.02"); print_info (")\n");
  print_info ("\n");

  print_info ("\n(Note: for multiple .pcd files, provide multiple -{fc,ps,opaque} parameters; they will be automatically assigned to the right file)\n");
}

// Create the PCLVisualizer object
boost::shared_ptr<pcl_visualization::PCLVisualizer> p;
ColorHandlerPtr color_handler;
GeometryHandlerPtr geometry_handler;
std::vector<double> fcolor_r, fcolor_b, fcolor_g;
bool fcolorparam = false;

struct EventHelper
{
  void cloud_cb (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr &cloud)
  {
      //std::cout << __PRETTY_FUNCTION__ << " " << cloud->width << std::endl;
    // Add the dataset with a XYZ and a random handler
  //  geometry_handler.reset (new pcl_visualization::PointCloudGeometryHandlerXYZ<pcl::PointCloud<pcl::PointXYZRGB> > (*cloud));

    //// If color was given, ues that
    //if (fcolorparam)
    //  color_handler.reset (new pcl_visualization::PointCloudColorHandlerCustom<pcl::PointCloud<pcl::PointXYZRGB> > (cloud, fcolor_r, fcolor_g, fcolor_b));
    //else
    //  color_handler.reset (new pcl_visualization::PointCloudColorHandlerRandom<pcl::PointCloud<pcl::PointXYZRGB> > (cloud));

    // Add the cloud to the renderer

    boost::mutex::scoped_lock lock(mutex_);
    if (!cloud)
      return;
    p->removePointCloud ("PCDCloud");
    p->addPointCloud (*cloud, "PCDCloud");
  }
};

/* ---[ */
int
  main (int argc, char** argv)
{
  srand (time (0));

  if (argc > 1)
  {
    for (int i = 1; i < argc; i++)
    {
      if (std::string(argv[i]) == "-h")
      {
        printHelp (argc, argv);
        return (-1);
      }
    }
  }

  // Command line parsing
  double bcolor[3] = {0, 0, 0};
  terminal_tools::parse_3x_arguments (argc, argv, "-bc", bcolor[0], bcolor[1], bcolor[2]);

  fcolorparam = terminal_tools::parse_multiple_3x_arguments (argc, argv, "-fc", fcolor_r, fcolor_g, fcolor_b);

  int psize = 0;
  terminal_tools::parse_argument (argc, argv, "-ps", psize);

  double opaque;
  terminal_tools::parse_argument (argc, argv, "-opaque", opaque);

  p.reset (new pcl_visualization::PCLVisualizer (argc, argv, "PCD viewer"));

//  // Change the cloud rendered point size
//  if (psize > 0)
//    p->setPointCloudRenderingProperties (pcl_visualization::PCL_VISUALIZER_POINT_SIZE, psize, "KinectCloud");
//
//  // Change the cloud rendered opacity
//  if (opaque >= 0)
//    p->setPointCloudRenderingProperties (pcl_visualization::PCL_VISUALIZER_OPACITY, opaque, "KinectCloud");

  p->setBackgroundColor (bcolor[0], bcolor[1], bcolor[2]);

  //boost::signals2::connection c = interface->registerCallback (boost::bind (&bla::blatestpointcloudrgb, *this, _1));
  //boost::function<void (boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >)> f = boost::bind (&bla::blatestpointcloudrgb, this, _1);
  //boost::signals2::connection c =
  //  interface->registerCallback <void(boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >)> (boost::bind (&bla::blatestpointcloudrgb, *this, _1).);

  // Read axes settings
  double axes  = 0.0;
  terminal_tools::parse_argument (argc, argv, "-ax", axes);
  if (axes != 0.0 && p)
  {
    double ax_x = 0.0, ax_y = 0.0, ax_z = 0.0;
    terminal_tools::parse_3x_arguments (argc, argv, "-ax_pos", ax_x, ax_y, ax_z, false);
    // Draw XYZ axes if command-line enabled
    p->addCoordinateSystem (axes, ax_x, ax_y, ax_z);
  }

  std::string pcd_file = "";
  terminal_tools::parse_argument (argc, argv, "-file", pcd_file);

  pcl::Grabber* interface = new pcl::PCDGrabber<pcl::PointXYZRGB>(pcd_file);

  EventHelper h;
  boost::function<void(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr&)> f = boost::bind(&EventHelper::cloud_cb, &h, _1);
  boost::signals2::connection c1 = interface->registerCallback (f);

  interface->start ();
  while (true)
  {
    usleep (10000);
    {
      boost::mutex::scoped_lock lock(mutex_);
      p->spinOnce ();
      if (p->wasStopped ())
        break;
    }
  }

  interface->stop ();
}
/* ]--- */
<commit_msg>added -dir, -fps and -repeat options<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  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 Willow Garage, Inc. 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.
 *
 * Author: Radu Bogdan rusu, Suat Gedikli
 *
 */
// PCL
#include <Eigen/Geometry>
#include <pcl/common/common.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/pcd_grabber.h>
#include <cfloat>
#include <pcl/visualization/point_cloud_handlers.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/histogram_visualizer.h>
#include <pcl/terminal_tools/print.h>
#include <pcl/terminal_tools/parse.h>
#include <pcl/terminal_tools/time.h>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

using terminal_tools::print_color;
using terminal_tools::print_error;
using terminal_tools::print_error;
using terminal_tools::print_warn;
using terminal_tools::print_info;
using terminal_tools::print_debug;
using terminal_tools::print_value;
using terminal_tools::print_highlight;
using terminal_tools::TT_BRIGHT;
using terminal_tools::TT_RED;
using terminal_tools::TT_GREEN;
using terminal_tools::TT_BLUE;
using namespace boost::filesystem;

typedef pcl_visualization::PointCloudColorHandler<pcl::PointCloud<pcl::PointXYZ> > ColorHandler;
typedef ColorHandler::Ptr ColorHandlerPtr;
typedef ColorHandler::ConstPtr ColorHandlerConstPtr;

typedef pcl_visualization::PointCloudGeometryHandler<pcl::PointCloud<pcl::PointXYZ> > GeometryHandler;
typedef GeometryHandler::Ptr GeometryHandlerPtr;
typedef GeometryHandler::ConstPtr GeometryHandlerConstPtr;
boost::mutex mutex_;

#define NORMALS_SCALE 0.01
#define PC_SCALE 0.001

void
printHelp (int argc, char **argv)
{
  //print_error ("Syntax is: %s <file_name 1..N>.pcd <options>\n", argv[0]);
  print_error ("Syntax is: %s <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -file file_name          = PCD file to be read from\n");
  print_info ("                     -dir directory_path      = directory path to PCD file(s) to be read from\n");
  print_info ("                     -fps frequency           = frames per second\n");
  print_info ("                     -repeat                  = optional parameter that tells wheter the PCD file(s) should be \"grabbed\" in a endless loop.\n");
  print_info ("                     -bc r,g,b                = background color\n");
  print_info ("                     -fc r,g,b                = foreground color\n");
  print_info ("                     -ps X                    = point size (");
  print_value ("1..64");
  print_info (") \n");
  print_info ("                     -opaque X                = rendered point cloud opacity (");
  print_value ("0..1");
  print_info (")\n");

  print_info ("                     -ax ");
  print_value ("n");
  print_info ("                    = enable on-screen display of ");
  print_color (stdout, TT_BRIGHT, TT_RED, "X");
  print_color (stdout, TT_BRIGHT, TT_GREEN, "Y");
  print_color (stdout, TT_BRIGHT, TT_BLUE, "Z");
  print_info (" axes and scale them to ");
  print_value ("n\n");
  print_info ("                     -ax_pos X,Y,Z            = if axes are enabled, set their X,Y,Z position in space (default ");
  print_value ("0,0,0");
  print_info (")\n");

  print_info ("\n");
  print_info ("                     -cam (*)                 = use given camera settings as initial view\n");
  print_info (stderr, " (*) [Clipping Range / Focal Point / Position / ViewUp / Distance / Window Size / Window Pos] or use a <filename.cam> that contains the same information.\n");

  print_info ("\n");
  print_info ("                     -multiview 0/1           = enable/disable auto-multi viewport rendering (default ");
  print_value ("disabled");
  print_info (")\n");
  print_info ("\n");

  print_info ("\n");
  print_info ("                     -normals 0/X             = disable/enable the display of every Xth point's surface normal as lines (default ");
  print_value ("disabled");
  print_info (")\n");
  print_info ("                     -normals_scale X         = resize the normal unit vector size to X (default ");
  print_value ("0.02");
  print_info (")\n");
  print_info ("\n");
  print_info ("                     -pc 0/X                  = disable/enable the display of every Xth point's principal curvatures as lines (default ");
  print_value ("disabled");
  print_info (")\n");
  print_info ("                     -pc_scale X              = resize the principal curvatures vectors size to X (default ");
  print_value ("0.02");
  print_info (")\n");
  print_info ("\n");

  print_info ("\n(Note: for multiple .pcd files, provide multiple -{fc,ps,opaque} parameters; they will be automatically assigned to the right file)\n");
}

// Create the PCLVisualizer object
boost::shared_ptr<pcl_visualization::PCLVisualizer> p;
ColorHandlerPtr color_handler;
GeometryHandlerPtr geometry_handler;
std::vector<double> fcolor_r, fcolor_b, fcolor_g;
bool fcolorparam = false;

struct EventHelper
{

  void cloud_cb (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr & cloud)
  {
    //std::cout << __PRETTY_FUNCTION__ << " " << cloud->width << std::endl;
    // Add the dataset with a XYZ and a random handler
    //  geometry_handler.reset (new pcl_visualization::PointCloudGeometryHandlerXYZ<pcl::PointCloud<pcl::PointXYZRGB> > (*cloud));

    //// If color was given, ues that
    //if (fcolorparam)
    //  color_handler.reset (new pcl_visualization::PointCloudColorHandlerCustom<pcl::PointCloud<pcl::PointXYZRGB> > (cloud, fcolor_r, fcolor_g, fcolor_b));
    //else
    //  color_handler.reset (new pcl_visualization::PointCloudColorHandlerRandom<pcl::PointCloud<pcl::PointXYZRGB> > (cloud));

    // Add the cloud to the renderer

    boost::mutex::scoped_lock lock (mutex_);
    if (!cloud)
      return;
    p->removePointCloud ("PCDCloud");
    p->addPointCloud (*cloud, "PCDCloud");
  }
};

/* ---[ */
int
main (int argc, char** argv)
{
  srand (time (0));

  if (argc > 1)
  {
    for (int i = 1; i < argc; i++)
    {
      if (std::string (argv[i]) == "-h")
      {
        printHelp (argc, argv);
        return (-1);
      }
    }
  }

  // Command line parsing
  double bcolor[3] = {0, 0, 0};
  terminal_tools::parse_3x_arguments (argc, argv, "-bc", bcolor[0], bcolor[1], bcolor[2]);

  fcolorparam = terminal_tools::parse_multiple_3x_arguments (argc, argv, "-fc", fcolor_r, fcolor_g, fcolor_b);

  int psize = 0;
  terminal_tools::parse_argument (argc, argv, "-ps", psize);

  double opaque;
  terminal_tools::parse_argument (argc, argv, "-opaque", opaque);

  p.reset (new pcl_visualization::PCLVisualizer (argc, argv, "PCD viewer"));

  //  // Change the cloud rendered point size
  //  if (psize > 0)
  //    p->setPointCloudRenderingProperties (pcl_visualization::PCL_VISUALIZER_POINT_SIZE, psize, "KinectCloud");
  //
  //  // Change the cloud rendered opacity
  //  if (opaque >= 0)
  //    p->setPointCloudRenderingProperties (pcl_visualization::PCL_VISUALIZER_OPACITY, opaque, "KinectCloud");

  p->setBackgroundColor (bcolor[0], bcolor[1], bcolor[2]);

  //boost::signals2::connection c = interface->registerCallback (boost::bind (&bla::blatestpointcloudrgb, *this, _1));
  //boost::function<void (boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >)> f = boost::bind (&bla::blatestpointcloudrgb, this, _1);
  //boost::signals2::connection c =
  //  interface->registerCallback <void(boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >)> (boost::bind (&bla::blatestpointcloudrgb, *this, _1).);

  // Read axes settings
  double axes = 0.0;
  terminal_tools::parse_argument (argc, argv, "-ax", axes);
  if (axes != 0.0 && p)
  {
    double ax_x = 0.0, ax_y = 0.0, ax_z = 0.0;
    terminal_tools::parse_3x_arguments (argc, argv, "-ax_pos", ax_x, ax_y, ax_z, false);
    // Draw XYZ axes if command-line enabled
    p->addCoordinateSystem (axes, ax_x, ax_y, ax_z);
  }

  pcl::Grabber* interface = 0;

  float frames_per_second = 0; // 0 means only if triggered!
  terminal_tools::parse (argc, argv, "-fps", frames_per_second);
  if (frames_per_second < 0)
    frames_per_second = 0.0;

  std::cout << terminal_tools::find_argument (argc, argv, "-repeat") << " : repaet" << std::endl;
  bool repeat = (terminal_tools::find_argument (argc, argv, "-repeat") != -1);

  std::cout << "fps: " << frames_per_second << " , repeat: " << repeat << std::endl;
  std::string path = "";
  terminal_tools::parse_argument (argc, argv, "-file", path);
  std::cout << "path: " << path << std::endl;
  if (path != "" && exists (path))
  {
    interface = new pcl::PCDGrabber<pcl::PointXYZ > (path, frames_per_second, repeat);
  }
  else
  {
    std::vector<std::string> pcd_files;
    terminal_tools::parse_argument (argc, argv, "-dir", path);
    std::cout << "path: " << path << std::endl;
    if (path != "" && exists (path))
    {
      directory_iterator end_itr;
      for (directory_iterator itr (path); itr != end_itr; ++itr)
      {
        if (!is_directory (itr->status()) && boost::algorithm::to_upper_copy(extension (itr->leaf())) == ".PCD" )
        {
          pcd_files.push_back (itr->path ().string());
          std::cout << "added: " << itr->path ().string() << std::endl;
        }
      }
    }
    else
    {
      std::cout << "Neither a pcd file given using the \"-file\" option, nor given a directory containing pcd files using the \"-dir\" option." << std::endl;
    }
    interface = new pcl::PCDGrabber<pcl::PointXYZ > (pcd_files, frames_per_second, repeat);
  }

  EventHelper h;
  boost::function<void(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&) > f = boost::bind (&EventHelper::cloud_cb, &h, _1);
  boost::signals2::connection c1 = interface->registerCallback (f);

  interface->start ();
  while (true)
  {
    usleep (10000);
    {
      boost::mutex::scoped_lock lock (mutex_);
      p->spinOnce ();
      if (p->wasStopped ())
        break;
    }
  }

  interface->stop ();
}
/* ]--- */
<|endoftext|>


<commit_before>
#include <boost/asio.hpp>
#include <google/protobuf/service.h>
#include <google/protobuf/descriptor.h>

#include "vtrc-bind.h"
#include "vtrc-function.h"

#include "vtrc-common/vtrc-data-queue.h"
#include "vtrc-common/vtrc-hash-iface.h"
#include "vtrc-common/vtrc-transformer-iface.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-rpc-controller.h"
#include "vtrc-common/vtrc-random-device.h"

#include "vtrc-protocol-layer-c.h"
#include "vtrc-transport-iface.h"

#include "vtrc-client.h"
#include "vtrc-chrono.h"

#include "protocol/vtrc-auth.pb.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"

namespace vtrc { namespace client {

    namespace gpb = google::protobuf;

    namespace {
        typedef vtrc::shared_ptr <
            vtrc_rpc_lowlevel::lowlevel_unit
        > lowlevel_unit_sptr;

        typedef vtrc::shared_ptr<gpb::Service> service_str;

        enum protocol_stage {
             STAGE_HELLO = 1
            ,STAGE_SETUP = 2
            ,STAGE_READY = 3
            ,STAGE_RPC   = 4
        };

    }

    struct protocol_layer_c::impl {

        typedef impl this_type;
        typedef protocol_layer_c parent_type;

        typedef vtrc::function<void (void)> stage_funcion_type;

        common::transport_iface     *connection_;
        protocol_layer_c            *parent_;
        stage_funcion_type           stage_call_;
        vtrc_client                 *client_;
        protocol_stage               stage_;

        impl( common::transport_iface *c, vtrc_client *client )
            :connection_(c)
            ,client_(client)
            ,stage_(STAGE_HELLO)
        {
            stage_call_ = vtrc::bind( &this_type::on_hello_call, this );
        }

        void change_stage( protocol_stage stage )
        {
            stage_ = stage;
            switch ( stage_ ) {
            case STAGE_HELLO:
                stage_call_ = vtrc::bind( &this_type::on_hello_call, this );
                break;
            case STAGE_SETUP:
                stage_call_ = vtrc::bind( &this_type::on_trans_setup, this );
                break;
            case STAGE_READY:
                stage_call_ = vtrc::bind( &this_type::on_server_ready, this );
                break;
            case STAGE_RPC:
                stage_call_ = vtrc::bind( &this_type::on_rpc_process, this );
                break;
            }
        }

        void init( )
        {

        }

        void check_disconnect_stage( )
        {
            switch ( stage_ ) {
            case STAGE_HELLO:
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Server in not ready");
                break;
            case STAGE_SETUP:
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INVALID_VALUE, "" ),
                            "Bad setup info.");
                break;
            case STAGE_READY:
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Bad session key.");
                break;
            case STAGE_RPC:
            default:
                break;
            }
        }

        vtrc_errors::container create_error( unsigned code,
                                             const std::string &add )
        {
            vtrc_errors::container cont;
            cont.set_code( code );
            cont.set_category( vtrc_errors::CATEGORY_INTERNAL );
            cont.set_additional( add );
        }

        const std::string &client_id( ) const
        {
            return client_->get_session_id( );
        }

        common::rpc_service_wrapper_sptr get_service_by_name(
                                                      const std::string &name )
        {
            return common::rpc_service_wrapper_sptr
                        (new common::rpc_service_wrapper(
                                             client_->get_rpc_handler( name )));
        }

        void pop_message( )
        {
            parent_->pop_message( );
        }

        void send_proto_message( const gpb::Message &mess ) const
        {
            std::string s(mess.SerializeAsString( ));
            connection_->write(s.c_str( ), s.size( ) );
        }

        void send_proto_message( const gpb::Message &mess,
                                 common::closure_type closure,
                                 bool on_send ) const
        {
            std::string s(mess.SerializeAsString( ));
            connection_->write(s.c_str( ), s.size( ), closure, on_send );
        }

        void process_event_impl( vtrc_client_wptr client,
                                 lowlevel_unit_sptr llu)
        {
            vtrc_client_sptr c(client.lock( ));
            if( !c ) return;
            parent_->make_call( llu );
        }

        void process_event( lowlevel_unit_sptr &llu )
        {
            client_->get_rpc_service( ).post(
                vtrc::bind( &this_type::process_event_impl, this,
                             client_->weak_from_this( ), llu));
        }

        void process_service( lowlevel_unit_sptr &llu )
        {

        }

        void process_internal( lowlevel_unit_sptr &llu )
        {

        }

        void process_call( lowlevel_unit_sptr &llu )
        {
            parent_->push_rpc_message( llu->id( ), llu );
        }

        void process_callback( lowlevel_unit_sptr &llu )
        {
            parent_->push_rpc_message( llu->id( ), llu );
        }

        void process_invalid( lowlevel_unit_sptr &llu )
        {
//            llu->Clear( );
//            parent_->send_message( *llu );
        }

        void on_ready( bool ready )
        {
            parent_->set_ready( ready );
            client_->on_ready_( );
        }

        void on_rpc_process( )
        {
            while( !parent_->message_queue( ).empty( ) ) {

                std::string &mess (parent_->message_queue( ).front( ));

                bool check = parent_->check_message( mess );

                lowlevel_unit_sptr llu(vtrc::make_shared<lowlevel_unit_type>());

                if( !check ) {

                    vtrc_errors::container *err = llu->mutable_error( );
                    err->set_code(vtrc_errors::ERR_PROTOCOL);
                    err->set_additional("Bad message was received");
                    err->set_fatal( true );

                    parent_->push_rpc_message_all( llu );
                    connection_->close( );

                    return;
                }

                parent_->parse_message( mess, *llu );

                switch( llu->info( ).message_type( ) ) {

                case vtrc_rpc_lowlevel::message_info::MESSAGE_EVENT:
                    process_event( llu );
                    break;
                case vtrc_rpc_lowlevel::message_info::MESSAGE_CALLBACK:
                    process_callback( llu );
                    break;
                case vtrc_rpc_lowlevel::message_info::MESSAGE_SERVICE:
                    process_service( llu );
                    break;
                case vtrc_rpc_lowlevel::message_info::MESSAGE_INTERNAL:
                    process_internal( llu );
                    break;
                case vtrc_rpc_lowlevel::message_info::MESSAGE_CALL:
                case vtrc_rpc_lowlevel::message_info::MESSAGE_INSERTION_CALL:
                    process_call( llu );
                    break;
                default:
                    process_invalid( llu );
                }

                pop_message( );
            }
        }

        void on_server_ready( )
        {

            std::string &mess = parent_->message_queue( ).front( );
            bool check = parent_->check_message( mess );

            vtrc_auth::init_capsule capsule;

            if( check ) {
                parent_->parse_message( mess, capsule );
            } else {
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Server's 'Ready' has bad hash. Bad session key." );
                connection_->close( );
                return;
            }

            if( !capsule.ready( ) ) {
                parent_->on_init_error(capsule.error( ),
                                       "Server is not ready; stage: 'Ready'");
            }

            pop_message( );

            change_stage( STAGE_RPC );

            on_ready( true );
        }

        void on_trans_setup( )
        {
            using namespace common::transformers;
            std::string &mess = parent_->message_queue( ).front( );
            bool check = parent_->check_message( mess );

            if( !check ) {
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Server's 'Setup' has bad hash." );
                connection_->close( );
                return;
            }

            vtrc_auth::init_capsule capsule;
            parent_->parse_message( mess, capsule );

            parent_->pop_message( );

            if( !capsule.ready( ) ) {
                parent_->on_init_error( capsule.error( ),
                                        "Server is not ready; stage: 'Setup'" );
                connection_->close( );
                return;
            }

            vtrc_auth::transformer_setup tsetup;

            tsetup.ParseFromString( capsule.body( ) );

            std::string key(client_->get_session_key( ));

            std::string s1(tsetup.salt1( ));
            std::string s2(tsetup.salt2( ));

            create_key( key, s1, s2, key );

            common::transformer_iface *new_transformer =
                                erseefor::create( key.c_str( ), key.size( ) );

            parent_->change_transformer( new_transformer );

            key.assign( client_->get_session_key( ) );
            generate_key_infos( key, s1, s2, key );

            tsetup.set_salt1( s1 );
            tsetup.set_salt2( s2 );

            common::transformer_iface *new_reverter =
                                erseefor::create( key.c_str( ), key.size( ) );

            parent_->change_revertor( new_reverter );

            capsule.set_ready( true );
            capsule.set_body( tsetup.SerializeAsString( ) );

            change_stage( STAGE_READY );

            send_proto_message( capsule );

        }

        void set_options( const boost::system::error_code &err )
        {
            if( !err ) {
                std::cout << "set opts\n";
                parent_->change_hash_maker(
                   common::hash::create_by_index( vtrc_auth::HASH_CRC_32 ));
            }
        }

        void on_hello_call( )
        {
            std::string &mess = parent_->message_queue( ).front( );
            bool check = parent_->check_message( mess );

            if( !check ) {
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Server's 'Hello' has bad hash." );
                connection_->close( );
                return;
            }

            vtrc_auth::init_capsule capsule;

            parent_->parse_message( mess, capsule );

            if( !capsule.ready( ) ) {
                parent_->on_init_error(capsule.error( ),
                                       "Server is not ready; stage: 'Hello'");
                connection_->close( );
                return;
            }

            pop_message( );

            vtrc_auth::client_selection init;

            capsule.set_ready( true );
            capsule.set_text( "Miten menee?" );

            bool key_set = client_->is_key_set( );

            if( !key_set ) {
                init.set_transform( vtrc_auth::TRANSFORM_NONE );
            } else {
                init.set_transform( vtrc_auth::TRANSFORM_ERSEEFOR );
                init.set_id( client_->get_session_id( ) );
            }

            init.set_hash( vtrc_auth::HASH_CRC_32 );

            capsule.set_body( init.SerializeAsString( ) );

            parent_->change_hash_checker(
               common::hash::create_by_index( vtrc_auth::HASH_CRC_32 ));

            change_stage( key_set ? STAGE_SETUP : STAGE_READY );

            send_proto_message( capsule,
                                vtrc::bind( &this_type::set_options, this, _1 ),
                                false );

        }

        void data_ready( )
        {
            stage_call_( );
        }

    };

    protocol_layer_c::protocol_layer_c( common::transport_iface *connection,
                                        vtrc::client::vtrc_client *client )
        :common::protocol_layer(connection, true)
        ,impl_(new impl(connection, client))
    {
        impl_->parent_ = this;
    }

    protocol_layer_c::~protocol_layer_c( )
    {
        delete impl_;
    }

    void protocol_layer_c::init( )
    {
        impl_->init( );
    }

    void protocol_layer_c::close( )
    {
        impl_->check_disconnect_stage( );
        impl_->client_->on_disconnect_( );
    }

    const std::string &protocol_layer_c::client_id( ) const
    {
        return impl_->client_id( );
    }

    void protocol_layer_c::on_data_ready( )
    {
        impl_->data_ready( );
    }

    void protocol_layer_c::on_init_error(const vtrc_errors::container &error,
                                         const char *message)
    {
        impl_->client_->on_init_error_( error, message );
    }

    common::rpc_service_wrapper_sptr protocol_layer_c::get_service_by_name(
                                                        const std::string &name)
    {
        return impl_->get_service_by_name( name );
    }

}}
<commit_msg>return<commit_after>
#include <boost/asio.hpp>
#include <google/protobuf/service.h>
#include <google/protobuf/descriptor.h>

#include "vtrc-bind.h"
#include "vtrc-function.h"

#include "vtrc-common/vtrc-data-queue.h"
#include "vtrc-common/vtrc-hash-iface.h"
#include "vtrc-common/vtrc-transformer-iface.h"
#include "vtrc-common/vtrc-call-context.h"
#include "vtrc-common/vtrc-rpc-controller.h"
#include "vtrc-common/vtrc-random-device.h"

#include "vtrc-protocol-layer-c.h"
#include "vtrc-transport-iface.h"

#include "vtrc-client.h"
#include "vtrc-chrono.h"

#include "protocol/vtrc-auth.pb.h"
#include "protocol/vtrc-rpc-lowlevel.pb.h"

namespace vtrc { namespace client {

    namespace gpb = google::protobuf;

    namespace {
        typedef vtrc::shared_ptr <
            vtrc_rpc_lowlevel::lowlevel_unit
        > lowlevel_unit_sptr;

        typedef vtrc::shared_ptr<gpb::Service> service_str;

        enum protocol_stage {
             STAGE_HELLO = 1
            ,STAGE_SETUP = 2
            ,STAGE_READY = 3
            ,STAGE_RPC   = 4
        };

    }

    struct protocol_layer_c::impl {

        typedef impl this_type;
        typedef protocol_layer_c parent_type;

        typedef vtrc::function<void (void)> stage_funcion_type;

        common::transport_iface     *connection_;
        protocol_layer_c            *parent_;
        stage_funcion_type           stage_call_;
        vtrc_client                 *client_;
        protocol_stage               stage_;

        impl( common::transport_iface *c, vtrc_client *client )
            :connection_(c)
            ,client_(client)
            ,stage_(STAGE_HELLO)
        {
            stage_call_ = vtrc::bind( &this_type::on_hello_call, this );
        }

        void change_stage( protocol_stage stage )
        {
            stage_ = stage;
            switch ( stage_ ) {
            case STAGE_HELLO:
                stage_call_ = vtrc::bind( &this_type::on_hello_call, this );
                break;
            case STAGE_SETUP:
                stage_call_ = vtrc::bind( &this_type::on_trans_setup, this );
                break;
            case STAGE_READY:
                stage_call_ = vtrc::bind( &this_type::on_server_ready, this );
                break;
            case STAGE_RPC:
                stage_call_ = vtrc::bind( &this_type::on_rpc_process, this );
                break;
            }
        }

        void init( )
        {

        }

        void check_disconnect_stage( )
        {
            switch ( stage_ ) {
            case STAGE_HELLO:
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Server in not ready");
                break;
            case STAGE_SETUP:
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INVALID_VALUE, "" ),
                            "Bad setup info.");
                break;
            case STAGE_READY:
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Bad session key.");
                break;
            case STAGE_RPC:
            default:
                break;
            }
        }

        vtrc_errors::container create_error( unsigned code,
                                             const std::string &add )
        {
            vtrc_errors::container cont;
            cont.set_code( code );
            cont.set_category( vtrc_errors::CATEGORY_INTERNAL );
            cont.set_additional( add );
            return cont;
        }

        const std::string &client_id( ) const
        {
            return client_->get_session_id( );
        }

        common::rpc_service_wrapper_sptr get_service_by_name(
                                                      const std::string &name )
        {
            return common::rpc_service_wrapper_sptr
                        (new common::rpc_service_wrapper(
                                             client_->get_rpc_handler( name )));
        }

        void pop_message( )
        {
            parent_->pop_message( );
        }

        void send_proto_message( const gpb::Message &mess ) const
        {
            std::string s(mess.SerializeAsString( ));
            connection_->write(s.c_str( ), s.size( ) );
        }

        void send_proto_message( const gpb::Message &mess,
                                 common::closure_type closure,
                                 bool on_send ) const
        {
            std::string s(mess.SerializeAsString( ));
            connection_->write(s.c_str( ), s.size( ), closure, on_send );
        }

        void process_event_impl( vtrc_client_wptr client,
                                 lowlevel_unit_sptr llu)
        {
            vtrc_client_sptr c(client.lock( ));
            if( !c ) return;
            parent_->make_call( llu );
        }

        void process_event( lowlevel_unit_sptr &llu )
        {
            client_->get_rpc_service( ).post(
                vtrc::bind( &this_type::process_event_impl, this,
                             client_->weak_from_this( ), llu));
        }

        void process_service( lowlevel_unit_sptr &llu )
        {

        }

        void process_internal( lowlevel_unit_sptr &llu )
        {

        }

        void process_call( lowlevel_unit_sptr &llu )
        {
            parent_->push_rpc_message( llu->id( ), llu );
        }

        void process_callback( lowlevel_unit_sptr &llu )
        {
            parent_->push_rpc_message( llu->id( ), llu );
        }

        void process_invalid( lowlevel_unit_sptr &llu )
        {
//            llu->Clear( );
//            parent_->send_message( *llu );
        }

        void on_ready( bool ready )
        {
            parent_->set_ready( ready );
            client_->on_ready_( );
        }

        void on_rpc_process( )
        {
            while( !parent_->message_queue( ).empty( ) ) {

                std::string &mess (parent_->message_queue( ).front( ));

                bool check = parent_->check_message( mess );

                lowlevel_unit_sptr llu(vtrc::make_shared<lowlevel_unit_type>());

                if( !check ) {

                    vtrc_errors::container *err = llu->mutable_error( );
                    err->set_code(vtrc_errors::ERR_PROTOCOL);
                    err->set_additional("Bad message was received");
                    err->set_fatal( true );

                    parent_->push_rpc_message_all( llu );
                    connection_->close( );

                    return;
                }

                parent_->parse_message( mess, *llu );

                switch( llu->info( ).message_type( ) ) {

                case vtrc_rpc_lowlevel::message_info::MESSAGE_EVENT:
                    process_event( llu );
                    break;
                case vtrc_rpc_lowlevel::message_info::MESSAGE_CALLBACK:
                    process_callback( llu );
                    break;
                case vtrc_rpc_lowlevel::message_info::MESSAGE_SERVICE:
                    process_service( llu );
                    break;
                case vtrc_rpc_lowlevel::message_info::MESSAGE_INTERNAL:
                    process_internal( llu );
                    break;
                case vtrc_rpc_lowlevel::message_info::MESSAGE_CALL:
                case vtrc_rpc_lowlevel::message_info::MESSAGE_INSERTION_CALL:
                    process_call( llu );
                    break;
                default:
                    process_invalid( llu );
                }

                pop_message( );
            }
        }

        void on_server_ready( )
        {

            std::string &mess = parent_->message_queue( ).front( );
            bool check = parent_->check_message( mess );

            vtrc_auth::init_capsule capsule;

            if( check ) {
                parent_->parse_message( mess, capsule );
            } else {
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Server's 'Ready' has bad hash. Bad session key." );
                connection_->close( );
                return;
            }

            if( !capsule.ready( ) ) {
                parent_->on_init_error(capsule.error( ),
                                       "Server is not ready; stage: 'Ready'");
            }

            pop_message( );

            change_stage( STAGE_RPC );

            on_ready( true );
        }

        void on_trans_setup( )
        {
            using namespace common::transformers;
            std::string &mess = parent_->message_queue( ).front( );
            bool check = parent_->check_message( mess );

            if( !check ) {
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Server's 'Setup' has bad hash." );
                connection_->close( );
                return;
            }

            vtrc_auth::init_capsule capsule;
            parent_->parse_message( mess, capsule );

            parent_->pop_message( );

            if( !capsule.ready( ) ) {
                parent_->on_init_error( capsule.error( ),
                                        "Server is not ready; stage: 'Setup'" );
                connection_->close( );
                return;
            }

            vtrc_auth::transformer_setup tsetup;

            tsetup.ParseFromString( capsule.body( ) );

            std::string key(client_->get_session_key( ));

            std::string s1(tsetup.salt1( ));
            std::string s2(tsetup.salt2( ));

            create_key( key, s1, s2, key );

            common::transformer_iface *new_transformer =
                                erseefor::create( key.c_str( ), key.size( ) );

            parent_->change_transformer( new_transformer );

            key.assign( client_->get_session_key( ) );
            generate_key_infos( key, s1, s2, key );

            tsetup.set_salt1( s1 );
            tsetup.set_salt2( s2 );

            common::transformer_iface *new_reverter =
                                erseefor::create( key.c_str( ), key.size( ) );

            parent_->change_revertor( new_reverter );

            capsule.set_ready( true );
            capsule.set_body( tsetup.SerializeAsString( ) );

            change_stage( STAGE_READY );

            send_proto_message( capsule );

        }

        void set_options( const boost::system::error_code &err )
        {
            if( !err ) {
                std::cout << "set opts\n";
                parent_->change_hash_maker(
                   common::hash::create_by_index( vtrc_auth::HASH_CRC_32 ));
            }
        }

        void on_hello_call( )
        {
            std::string &mess = parent_->message_queue( ).front( );
            bool check = parent_->check_message( mess );

            if( !check ) {
                parent_->on_init_error(
                            create_error( vtrc_errors::ERR_INTERNAL, "" ),
                            "Server's 'Hello' has bad hash." );
                connection_->close( );
                return;
            }

            vtrc_auth::init_capsule capsule;

            parent_->parse_message( mess, capsule );

            if( !capsule.ready( ) ) {
                parent_->on_init_error(capsule.error( ),
                                       "Server is not ready; stage: 'Hello'");
                connection_->close( );
                return;
            }

            pop_message( );

            vtrc_auth::client_selection init;

            capsule.set_ready( true );
            capsule.set_text( "Miten menee?" );

            bool key_set = client_->is_key_set( );

            if( !key_set ) {
                init.set_transform( vtrc_auth::TRANSFORM_NONE );
            } else {
                init.set_transform( vtrc_auth::TRANSFORM_ERSEEFOR );
                init.set_id( client_->get_session_id( ) );
            }

            init.set_hash( vtrc_auth::HASH_CRC_32 );

            capsule.set_body( init.SerializeAsString( ) );

            parent_->change_hash_checker(
               common::hash::create_by_index( vtrc_auth::HASH_CRC_32 ));

            change_stage( key_set ? STAGE_SETUP : STAGE_READY );

            send_proto_message( capsule,
                                vtrc::bind( &this_type::set_options, this, _1 ),
                                false );

        }

        void data_ready( )
        {
            stage_call_( );
        }

    };

    protocol_layer_c::protocol_layer_c( common::transport_iface *connection,
                                        vtrc::client::vtrc_client *client )
        :common::protocol_layer(connection, true)
        ,impl_(new impl(connection, client))
    {
        impl_->parent_ = this;
    }

    protocol_layer_c::~protocol_layer_c( )
    {
        delete impl_;
    }

    void protocol_layer_c::init( )
    {
        impl_->init( );
    }

    void protocol_layer_c::close( )
    {
        impl_->check_disconnect_stage( );
        impl_->client_->on_disconnect_( );
    }

    const std::string &protocol_layer_c::client_id( ) const
    {
        return impl_->client_id( );
    }

    void protocol_layer_c::on_data_ready( )
    {
        impl_->data_ready( );
    }

    void protocol_layer_c::on_init_error(const vtrc_errors::container &error,
                                         const char *message)
    {
        impl_->client_->on_init_error_( error, message );
    }

    common::rpc_service_wrapper_sptr protocol_layer_c::get_service_by_name(
                                                        const std::string &name)
    {
        return impl_->get_service_by_name( name );
    }

}}
<|endoftext|>


<commit_before>#include "MazeFileUtilities.h"

#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>

#ifdef _WIN32
    #include <windows.h>
#elif __linux
    #include <limits.h>
    #include <unistd.h>
#endif

namespace sim {

std::string getProjectDirectory(){

    // This approach is claimed to be more reliable than argv[0] on windows
    // and linux.  On Windows GetModuleFileName is the directory to the executable
    // which is located in /mms/src/Debug/.  On linux /proc/self/exe is a path to exe.
    // This aproach does not work for all flavors to Linux, should on the common.
    // executable on Linux is located at /mms/bin/

    std::string path;

#ifdef _WIN32
    char result[MAX_PATH];
    path = std::string(result, GetModuleFileName(NULL, result, MAX_PATH));
    path = path.substr(0, path.find_last_of("\\/"));; // Remove the executable name as it is part of path
    path += "\\..\\..\\"; // Point to /mms/
    // Windows uses \ in directory
#elif __linux
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    path = std::string(result, (count > 0) ? count : 0);
    path = path.substr(0, path.find_last_of("\\/"));; // Remove the executable name as it is part of path
    path += "/../"; // Point to /mms/
#endif

    return path;
}

std::string getMazeFileDirPath(){

    std::string path;

    path = getProjectDirectory();

    // Append mazeFile directory path from the root of the project
    path += "src/maze_files/";

    return path;
}

/*int mazeFileWidth(std::string mazeFilePath){

}

int mazeFileHeight(std::string mazeFilePath){

}
*/

bool checkValidMazeFile(std::string mazeFilePath){

    // TODO: Ensure that you have unique y values for all x values
    // TODO: Ensure that the walls line up
    // TODO: Make a mazeFileValidator - gets height, width, valid, etc

    // This function validates following:
    // 1.) There are an equal number of y values for each x value
    // 2.) All the x and y values are unique
    // 3.) The walls are valid

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    // Initialize a string variable
    std::string line("");

    if (file.is_open()){

        // Vector that counts the number of y values colums for each x value // TODO
        std::vector<int> counts;
        counts.push_back(0);
        int xValue = 0;

        while (getline(file, line)){
            std::istringstream iss(line);
            std::vector<std::string> tokens;
            copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
                 std::back_inserter<std::vector<std::string> >(tokens));

            // Counting logic // TODO
            /*if (tokens.at(0) == xValue){
                counts.at(xValue) += 1;
            }
            else{
                xValue = tokens.at(0);
                counts.push_back(1);
            }*/
        }

        file.close();

        /*int numberOfYValues = counts.at(0);
        for (int i = 1; i < counts.size(); i += 1){
            if (counts.at(i) != numberOfYValues){
                return 0;
            }
        }*/

    }

    // false indicates invalid file
    return false;
}

bool checkValidMazeFileTom(std::string mazeFilePath, int height, int width){

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    if (!file.is_open())
        return false; // Error opening file

    // Initialize a string variable
    std::string line("");

    int x_pos = 0;
    int y_pos = 0;

    int expected_x_pos = 0;
    int expected_y_pos = 0;

    int current_int = 0;

    while (std::getline(file, line)){
        for (int i = 0; i < 6; i += 1){

            try { // When did this happen << ?
                current_int = std::stoi(line, nullptr, 10);  //Attempt to get an integer which is followed by a space
            }
            catch (const std::invalid_argument& ia) {
                return false; // If not then something in the maze file is not valid
            }
            if (i == 0){ // X Pos
                if (current_int != expected_x_pos){
                    return false;
                }
                x_pos = current_int;
                if (x_pos == width)
                    return false; // Too many lines, RUN
            }
            if (i == 1){ // Y Pos
                if (current_int != expected_y_pos){
                    return false;
                }
                if (current_int == height - 1) { // Wrap Around
                    expected_y_pos = 0;
                    expected_x_pos += 1; // X-Pos will increase
                } else{
                    expected_y_pos += 1;
                }
                x_pos = current_int;
            }
            if (i > 1){ // Wall Values - check if 1 or 0
                if (current_int != 0 && current_int != 1){
                    return false;
                }
            }
            std::size_t found = line.find_first_of(" ");
            if (found != std::string::npos) { // extra space exists in the string
                line = line.substr(line.find_first_of(" ") + 1, line.length());
                if (i == 5){
                    return false; // return false if more spaces after last digit remain
                }
            }
            else{
                if (i != 5)
                    return false; // If no more spaces before the last digit that means the line
                                  // does not have enough digits
            }
        }
        if (expected_x_pos == width)
            break;
    }

    if (x_pos != width && y_pos != 0)
        return false; //Not all lines present in the last group

    return true; //should be fine

}

} // namespace sim
<commit_msg>Changed the Maze Validator exception<commit_after>#include "MazeFileUtilities.h"

#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>

#ifdef _WIN32
    #include <windows.h>
#elif __linux
    #include <limits.h>
    #include <unistd.h>
#endif

namespace sim {

std::string getProjectDirectory(){

    // This approach is claimed to be more reliable than argv[0] on windows
    // and linux.  On Windows GetModuleFileName is the directory to the executable
    // which is located in /mms/src/Debug/.  On linux /proc/self/exe is a path to exe.
    // This aproach does not work for all flavors to Linux, should on the common.
    // executable on Linux is located at /mms/bin/

    std::string path;

#ifdef _WIN32
    char result[MAX_PATH];
    path = std::string(result, GetModuleFileName(NULL, result, MAX_PATH));
    path = path.substr(0, path.find_last_of("\\/"));; // Remove the executable name as it is part of path
    path += "\\..\\..\\"; // Point to /mms/
    // Windows uses \ in directory
#elif __linux
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    path = std::string(result, (count > 0) ? count : 0);
    path = path.substr(0, path.find_last_of("\\/"));; // Remove the executable name as it is part of path
    path += "/../"; // Point to /mms/
#endif

    return path;
}

std::string getMazeFileDirPath(){

    std::string path;

    path = getProjectDirectory();

    // Append mazeFile directory path from the root of the project
    path += "src/maze_files/";

    return path;
}

/*int mazeFileWidth(std::string mazeFilePath){

}

int mazeFileHeight(std::string mazeFilePath){

}
*/

bool checkValidMazeFile(std::string mazeFilePath){

    // TODO: Ensure that you have unique y values for all x values
    // TODO: Ensure that the walls line up
    // TODO: Make a mazeFileValidator - gets height, width, valid, etc

    // This function validates following:
    // 1.) There are an equal number of y values for each x value
    // 2.) All the x and y values are unique
    // 3.) The walls are valid

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    // Initialize a string variable
    std::string line("");

    if (file.is_open()){

        // Vector that counts the number of y values colums for each x value // TODO
        std::vector<int> counts;
        counts.push_back(0);
        int xValue = 0;

        while (getline(file, line)){
            std::istringstream iss(line);
            std::vector<std::string> tokens;
            copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
                 std::back_inserter<std::vector<std::string> >(tokens));

            // Counting logic // TODO
            /*if (tokens.at(0) == xValue){
                counts.at(xValue) += 1;
            }
            else{
                xValue = tokens.at(0);
                counts.push_back(1);
            }*/
        }

        file.close();

        /*int numberOfYValues = counts.at(0);
        for (int i = 1; i < counts.size(); i += 1){
            if (counts.at(i) != numberOfYValues){
                return 0;
            }
        }*/

    }

    // false indicates invalid file
    return false;
}

bool checkValidMazeFileTom(std::string mazeFilePath, int height, int width){

    // Create the file object
    std::ifstream file(mazeFilePath.c_str());

    if (!file.is_open())
        return false; // Error opening file

    // Initialize a string variable
    std::string line("");

    int x_pos = 0;
    int y_pos = 0;

    int expected_x_pos = 0;
    int expected_y_pos = 0;

    int current_int = 0;

    while (std::getline(file, line)){
        for (int i = 0; i < 6; i += 1){

            try { // When did this happen << ?
                current_int = std::stoi(line, nullptr, 10);  //Attempt to get an integer which is followed by a space
            }
            //catch (const std::invalid_argument& ia) { // TODO: Tomasz
            catch (...) {
                return false; // If not then something in the maze file is not valid
            }
            if (i == 0){ // X Pos
                if (current_int != expected_x_pos){
                    return false;
                }
                x_pos = current_int;
                if (x_pos == width)
                    return false; // Too many lines, RUN
            }
            if (i == 1){ // Y Pos
                if (current_int != expected_y_pos){
                    return false;
                }
                if (current_int == height - 1) { // Wrap Around
                    expected_y_pos = 0;
                    expected_x_pos += 1; // X-Pos will increase
                } else{
                    expected_y_pos += 1;
                }
                x_pos = current_int;
            }
            if (i > 1){ // Wall Values - check if 1 or 0
                if (current_int != 0 && current_int != 1){
                    return false;
                }
            }
            std::size_t found = line.find_first_of(" ");
            if (found != std::string::npos) { // extra space exists in the string
                line = line.substr(line.find_first_of(" ") + 1, line.length());
                if (i == 5){
                    return false; // return false if more spaces after last digit remain
                }
            }
            else{
                if (i != 5)
                    return false; // If no more spaces before the last digit that means the line
                                  // does not have enough digits
            }
        }
        if (expected_x_pos == width)
            break;
    }

    if (x_pos != width && y_pos != 0)
        return false; //Not all lines present in the last group

    return true; //should be fine

}

} // namespace sim
<|endoftext|>


<commit_before>// Copyright (c) 2016-2019 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_BUFFER_INPUT_HPP
#define TAO_PEGTL_BUFFER_INPUT_HPP

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <stdexcept>
#include <string>

#include "config.hpp"
#include "eol.hpp"
#include "memory_input.hpp"
#include "position.hpp"
#include "tracking_mode.hpp"

#include "internal/action_input.hpp"
#include "internal/bump.hpp"
#include "internal/iterator.hpp"
#include "internal/marker.hpp"

namespace TAO_PEGTL_NAMESPACE
{
   template< typename Reader, typename Eol = eol::lf_crlf, typename Source = std::string, std::size_t Chunk = 64 >
   class buffer_input
   {
   public:
      using reader_t = Reader;

      using eol_t = Eol;
      using source_t = Source;

      using iterator_t = internal::iterator;

      using action_t = internal::action_input< buffer_input >;

      static constexpr std::size_t chunk_size = Chunk;
      static constexpr tracking_mode tracking_mode_v = tracking_mode::eager;

      template< typename T, typename... As >
      buffer_input( T&& in_source, const std::size_t maximum, As&&... as )
         : m_reader( std::forward< As >( as )... ),
           m_maximum( maximum + Chunk ),
           m_buffer( new char[ maximum + Chunk ] ),
           m_current( m_buffer.get() ),
           m_end( m_buffer.get() ),
           m_source( std::forward< T >( in_source ) )
      {
         static_assert( Chunk, "zero chunk size not implemented" );
         assert( m_maximum > maximum );  // Catches overflow; change to >= when zero chunk size is implemented.
      }

      buffer_input( const buffer_input& ) = delete;
      buffer_input( buffer_input&& ) = delete;

      ~buffer_input() = default;

      void operator=( const buffer_input& ) = delete;
      void operator=( buffer_input&& ) = delete;

      [[nodiscard]] bool empty()
      {
         require( 1 );
         return m_current.data == m_end;
      }

      [[nodiscard]] std::size_t size( const std::size_t amount )
      {
         require( amount );
         return buffer_occupied();
      }

      [[nodiscard]] const char* current() const noexcept
      {
         return m_current.data;
      }

      [[nodiscard]] const char* end( const std::size_t amount )
      {
         require( amount );
         return m_end;
      }

      [[nodiscard]] std::size_t byte() const noexcept
      {
         return m_current.byte;
      }

      [[nodiscard]] std::size_t line() const noexcept
      {
         return m_current.line;
      }

      [[nodiscard]] std::size_t byte_in_line() const noexcept
      {
         return m_current.byte_in_line;
      }

      [[nodiscard]] const Source& source() const noexcept
      {
         return m_source;
      }

      [[nodiscard]] char peek_char( const std::size_t offset = 0 ) const noexcept
      {
         return m_current.data[ offset ];
      }

      [[nodiscard]] std::uint8_t peek_uint8( const std::size_t offset = 0 ) const noexcept
      {
         return static_cast< std::uint8_t >( peek_char( offset ) );
      }

      void bump( const std::size_t in_count = 1 ) noexcept
      {
         internal::bump( m_current, in_count, Eol::ch );
      }

      void bump_in_this_line( const std::size_t in_count = 1 ) noexcept
      {
         internal::bump_in_this_line( m_current, in_count );
      }

      void bump_to_next_line( const std::size_t in_count = 1 ) noexcept
      {
         internal::bump_to_next_line( m_current, in_count );
      }

      void discard() noexcept
      {
         if( m_current.data > m_buffer.get() + Chunk ) {
            const auto s = m_end - m_current.data;
            std::memmove( m_buffer.get(), m_current.data, s );
            m_current.data = m_buffer.get();
            m_end = m_buffer.get() + s;
         }
      }

      void require( const std::size_t amount )
      {
         if( m_current.data + amount <= m_end ) {
            return;
         }
         if( m_current.data + amount > m_buffer.get() + m_maximum ) {
            throw std::runtime_error( "require beyond end of buffer" );
         }
         if( const auto r = m_reader( m_end, ( std::min )( buffer_free_after_end(), ( std::max )( amount, Chunk ) ) ) ) {
            m_end += r;
         }
      }

      template< rewind_mode M >
      [[nodiscard]] internal::marker< iterator_t, M > mark() noexcept
      {
         return internal::marker< iterator_t, M >( m_current );
      }

      [[nodiscard]] TAO_PEGTL_NAMESPACE::position position( const iterator_t& it ) const
      {
         return TAO_PEGTL_NAMESPACE::position( it, m_source );
      }

      [[nodiscard]] TAO_PEGTL_NAMESPACE::position position() const
      {
         return position( m_current );
      }

      [[nodiscard]] const iterator_t& iterator() const noexcept
      {
         return m_current;
      }

      [[nodiscard]] std::size_t buffer_capacity() const noexcept
      {
         return m_maximum;
      }

      [[nodiscard]] std::size_t buffer_occupied() const noexcept
      {
         assert( m_end >= m_current.data );
         return std::size_t( m_end - m_current.data );
      }

      [[nodiscard]] std::size_t buffer_free_before_current() const noexcept
      {
         assert( m_current.data >= m_buffer.get() );
         return std::size_t( m_current.data - m_buffer.get() );
      }

      [[nodiscard]] std::size_t buffer_free_after_end() const noexcept
      {
         assert( m_buffer.get() + m_maximum >= m_end );
         return std::size_t( m_buffer.get() + m_maximum - m_end );
      }

   private:
      Reader m_reader;
      std::size_t m_maximum;
      std::unique_ptr< char[] > m_buffer;  // NOLINT
      iterator_t m_current;
      char* m_end;
      const Source m_source;
   };

}  // namespace TAO_PEGTL_NAMESPACE

#endif
<commit_msg>Fix exception.<commit_after>// Copyright (c) 2016-2019 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_BUFFER_INPUT_HPP
#define TAO_PEGTL_BUFFER_INPUT_HPP

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <stdexcept>
#include <string>

#include "config.hpp"
#include "eol.hpp"
#include "memory_input.hpp"
#include "position.hpp"
#include "tracking_mode.hpp"

#include "internal/action_input.hpp"
#include "internal/bump.hpp"
#include "internal/iterator.hpp"
#include "internal/marker.hpp"

namespace TAO_PEGTL_NAMESPACE
{
   template< typename Reader, typename Eol = eol::lf_crlf, typename Source = std::string, std::size_t Chunk = 64 >
   class buffer_input
   {
   public:
      using reader_t = Reader;

      using eol_t = Eol;
      using source_t = Source;

      using iterator_t = internal::iterator;

      using action_t = internal::action_input< buffer_input >;

      static constexpr std::size_t chunk_size = Chunk;
      static constexpr tracking_mode tracking_mode_v = tracking_mode::eager;

      template< typename T, typename... As >
      buffer_input( T&& in_source, const std::size_t maximum, As&&... as )
         : m_reader( std::forward< As >( as )... ),
           m_maximum( maximum + Chunk ),
           m_buffer( new char[ maximum + Chunk ] ),
           m_current( m_buffer.get() ),
           m_end( m_buffer.get() ),
           m_source( std::forward< T >( in_source ) )
      {
         static_assert( Chunk, "zero chunk size not implemented" );
         assert( m_maximum > maximum );  // Catches overflow; change to >= when zero chunk size is implemented.
      }

      buffer_input( const buffer_input& ) = delete;
      buffer_input( buffer_input&& ) = delete;

      ~buffer_input() = default;

      void operator=( const buffer_input& ) = delete;
      void operator=( buffer_input&& ) = delete;

      [[nodiscard]] bool empty()
      {
         require( 1 );
         return m_current.data == m_end;
      }

      [[nodiscard]] std::size_t size( const std::size_t amount )
      {
         require( amount );
         return buffer_occupied();
      }

      [[nodiscard]] const char* current() const noexcept
      {
         return m_current.data;
      }

      [[nodiscard]] const char* end( const std::size_t amount )
      {
         require( amount );
         return m_end;
      }

      [[nodiscard]] std::size_t byte() const noexcept
      {
         return m_current.byte;
      }

      [[nodiscard]] std::size_t line() const noexcept
      {
         return m_current.line;
      }

      [[nodiscard]] std::size_t byte_in_line() const noexcept
      {
         return m_current.byte_in_line;
      }

      [[nodiscard]] const Source& source() const noexcept
      {
         return m_source;
      }

      [[nodiscard]] char peek_char( const std::size_t offset = 0 ) const noexcept
      {
         return m_current.data[ offset ];
      }

      [[nodiscard]] std::uint8_t peek_uint8( const std::size_t offset = 0 ) const noexcept
      {
         return static_cast< std::uint8_t >( peek_char( offset ) );
      }

      void bump( const std::size_t in_count = 1 ) noexcept
      {
         internal::bump( m_current, in_count, Eol::ch );
      }

      void bump_in_this_line( const std::size_t in_count = 1 ) noexcept
      {
         internal::bump_in_this_line( m_current, in_count );
      }

      void bump_to_next_line( const std::size_t in_count = 1 ) noexcept
      {
         internal::bump_to_next_line( m_current, in_count );
      }

      void discard() noexcept
      {
         if( m_current.data > m_buffer.get() + Chunk ) {
            const auto s = m_end - m_current.data;
            std::memmove( m_buffer.get(), m_current.data, s );
            m_current.data = m_buffer.get();
            m_end = m_buffer.get() + s;
         }
      }

      void require( const std::size_t amount )
      {
         if( m_current.data + amount <= m_end ) {
            return;
         }
         if( m_current.data + amount > m_buffer.get() + m_maximum ) {
            throw std::overflow_error( "require beyond end of buffer" );
         }
         if( const auto r = m_reader( m_end, ( std::min )( buffer_free_after_end(), ( std::max )( amount, Chunk ) ) ) ) {
            m_end += r;
         }
      }

      template< rewind_mode M >
      [[nodiscard]] internal::marker< iterator_t, M > mark() noexcept
      {
         return internal::marker< iterator_t, M >( m_current );
      }

      [[nodiscard]] TAO_PEGTL_NAMESPACE::position position( const iterator_t& it ) const
      {
         return TAO_PEGTL_NAMESPACE::position( it, m_source );
      }

      [[nodiscard]] TAO_PEGTL_NAMESPACE::position position() const
      {
         return position( m_current );
      }

      [[nodiscard]] const iterator_t& iterator() const noexcept
      {
         return m_current;
      }

      [[nodiscard]] std::size_t buffer_capacity() const noexcept
      {
         return m_maximum;
      }

      [[nodiscard]] std::size_t buffer_occupied() const noexcept
      {
         assert( m_end >= m_current.data );
         return std::size_t( m_end - m_current.data );
      }

      [[nodiscard]] std::size_t buffer_free_before_current() const noexcept
      {
         assert( m_current.data >= m_buffer.get() );
         return std::size_t( m_current.data - m_buffer.get() );
      }

      [[nodiscard]] std::size_t buffer_free_after_end() const noexcept
      {
         assert( m_buffer.get() + m_maximum >= m_end );
         return std::size_t( m_buffer.get() + m_maximum - m_end );
      }

   private:
      Reader m_reader;
      std::size_t m_maximum;
      std::unique_ptr< char[] > m_buffer;  // NOLINT
      iterator_t m_current;
      char* m_end;
      const Source m_source;
   };

}  // namespace TAO_PEGTL_NAMESPACE

#endif
<|endoftext|>