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

#include "kateprojectpluginview.h"
#include "kateprojectpluginview.moc"

#include <kate/application.h>
#include <ktexteditor/view.h>
#include <ktexteditor/document.h>

#include <kaction.h>
#include <kactioncollection.h>
#include <klocale.h>
#include <kpluginfactory.h>
#include <kpluginloader.h>
#include <kaboutdata.h>

#include <KFileDialog>
#include <QDialog>
#include <QVBoxLayout>

K_PLUGIN_FACTORY(KateProjectPluginFactory, registerPlugin<KateProjectPlugin>();)
K_EXPORT_PLUGIN(KateProjectPluginFactory(KAboutData("project","kateprojectplugin",ki18n("Hello World"), "0.1", ki18n("Example kate plugin"))) )

KateProjectPluginView::KateProjectPluginView( KateProjectPlugin *plugin, Kate::MainWindow *mainWin )
    : Kate::PluginView( mainWin )
    , Kate::XMLGUIClient(KateProjectPluginFactory::componentData())
    , m_plugin (plugin)
{
  /**
   * add us to gui
   */
  mainWindow()->guiFactory()->addClient( this );

  /**
   * create toolview
   */
  m_toolView = mainWindow()->createToolView ("kateproject", Kate::MainWindow::Left, SmallIcon("project-open"), i18n("Projects"));

  /**
   * populate the toolview
   */
  m_toolBox = new QToolBox (m_toolView);

  /**
   * create views for all already existing projects
   */
  foreach (KateProject *project, m_plugin->projects())
    viewForProject (project);

  /**
   * connect to important signals, e.g. for auto project view creation
   */
  connect (m_plugin, SIGNAL(projectCreated (KateProject *)), this, SLOT(viewForProject (KateProject *)));
  connect (mainWindow(), SIGNAL(viewChanged ()), this, SLOT(slotViewChanged ()));
  connect (m_toolBox, SIGNAL(currentChanged (int)), this, SLOT(slotCurrentChanged (int)));

  /**
   * trigger once view change, dummy index
   */
  slotCurrentChanged (0);
}

KateProjectPluginView::~KateProjectPluginView()
{
  /**
   * cu toolview
   */
  delete m_toolView;

  /**
   * cu gui client
   */
  mainWindow()->guiFactory()->removeClient( this );
}

KateProjectView *KateProjectPluginView::viewForProject (KateProject *project)
{
  /**
   * needs valid project
   */
  Q_ASSERT (project);

  /**
   * existing view?
   */
  if (m_project2View.contains (project))
    return m_project2View.value (project);

  /**
   * create new view
   */
   KateProjectView *view = new KateProjectView (this, project);

   /**
    * attach to toolbox
    */
   m_toolBox->addItem (view, project->name());

   /**
    * remember and return it
    */
   m_project2View[project] = view;
   return view;
}

void KateProjectPluginView::readSessionConfig( KConfigBase* config, const QString& groupPrefix )
{
  // If you have session-dependant settings, load them here.
  // If you have application wide settings, you have to read your own KConfig,
  // see the Kate::Plugin docs for more information.
  Q_UNUSED( config );
  Q_UNUSED( groupPrefix );
}

void KateProjectPluginView::writeSessionConfig( KConfigBase* config, const QString& groupPrefix )
{
  // If you have session-dependant settings, save them here.
  // If you have application wide settings, you have to create your own KConfig,
  // see the Kate::Plugin docs for more information.
  Q_UNUSED( config );
  Q_UNUSED( groupPrefix );
}

QString KateProjectPluginView::projectFileName ()
{
  QWidget *active = m_toolBox->currentWidget ();
  if (!active)
    return QString ();

  return static_cast<KateProjectView *> (active)->project()->fileName ();
}

QStringList KateProjectPluginView::projectFiles ()
{
  KateProjectView *active = static_cast<KateProjectView *> (m_toolBox->currentWidget ());
  if (!active)
    return QStringList ();

  return active->project()->files ();
}

void KateProjectPluginView::slotViewChanged ()
{
  /**
   * get active view
   */
  KTextEditor::View *activeView = mainWindow()->activeView ();

  /**
   * update pointer, maybe disconnect before
   */
  if (m_activeTextEditorView)
    m_activeTextEditorView->document()->disconnect (this);
  m_activeTextEditorView = activeView;

  /**
   * no current active view, return
   */
  if (!m_activeTextEditorView)
    return;

  /**
   * connect to url changed, for auto load
   */
  connect (m_activeTextEditorView->document(), SIGNAL(documentUrlChanged (KTextEditor::Document *)), this, SLOT(slotDocumentUrlChanged (KTextEditor::Document *)));

  /**
   * trigger slot once
   */
  slotDocumentUrlChanged (m_activeTextEditorView->document());
}

void KateProjectPluginView::slotCurrentChanged (int)
{
  /**
   * we might need to highlight other document
   */
  slotViewChanged ();

  /**
   * project file name might have changed
   */
  emit projectFileNameChanged ();
}

void KateProjectPluginView::slotDocumentUrlChanged (KTextEditor::Document *document)
{
  /**
   * abort if empty url or no local path
   */
  if (document->url().isEmpty() || !document->url().isLocalFile())
    return;

  /**
   * search matching project
   */
  KateProject *project = m_plugin->projectForUrl (document->url());
  if (!project)
    return;

  /**
   * get active project view and switch it, if it is for a different project
   */
  KateProjectView *active = static_cast<KateProjectView *> (m_toolBox->currentWidget ());
  if (active != m_project2View.value (project)) {
      /**
       * switch view and return, we will be called again automatically by the slotCurrentChanged!
       */
      m_toolBox->setCurrentWidget (m_project2View.value (project));
      return;
  }

  /**
   * get local filename and then select it
   */
  active->selectFile (document->url().toLocalFile ());
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>allow again project view changes via toolbox<commit_after>/*  This file is part of the Kate project.
 *
 *  Copyright (C) 2010 Christoph Cullmann <cullmann@kde.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */

#include "kateprojectpluginview.h"
#include "kateprojectpluginview.moc"

#include <kate/application.h>
#include <ktexteditor/view.h>
#include <ktexteditor/document.h>

#include <kaction.h>
#include <kactioncollection.h>
#include <klocale.h>
#include <kpluginfactory.h>
#include <kpluginloader.h>
#include <kaboutdata.h>

#include <KFileDialog>
#include <QDialog>
#include <QVBoxLayout>

K_PLUGIN_FACTORY(KateProjectPluginFactory, registerPlugin<KateProjectPlugin>();)
K_EXPORT_PLUGIN(KateProjectPluginFactory(KAboutData("project","kateprojectplugin",ki18n("Hello World"), "0.1", ki18n("Example kate plugin"))) )

KateProjectPluginView::KateProjectPluginView( KateProjectPlugin *plugin, Kate::MainWindow *mainWin )
    : Kate::PluginView( mainWin )
    , Kate::XMLGUIClient(KateProjectPluginFactory::componentData())
    , m_plugin (plugin)
{
  /**
   * add us to gui
   */
  mainWindow()->guiFactory()->addClient( this );

  /**
   * create toolview
   */
  m_toolView = mainWindow()->createToolView ("kateproject", Kate::MainWindow::Left, SmallIcon("project-open"), i18n("Projects"));

  /**
   * populate the toolview
   */
  m_toolBox = new QToolBox (m_toolView);

  /**
   * create views for all already existing projects
   */
  foreach (KateProject *project, m_plugin->projects())
    viewForProject (project);

  /**
   * connect to important signals, e.g. for auto project view creation
   */
  connect (m_plugin, SIGNAL(projectCreated (KateProject *)), this, SLOT(viewForProject (KateProject *)));
  connect (mainWindow(), SIGNAL(viewChanged ()), this, SLOT(slotViewChanged ()));
  connect (m_toolBox, SIGNAL(currentChanged (int)), this, SLOT(slotCurrentChanged (int)));

  /**
   * trigger once view change, to highlight right document
   */
  slotViewChanged ();
}

KateProjectPluginView::~KateProjectPluginView()
{
  /**
   * cu toolview
   */
  delete m_toolView;

  /**
   * cu gui client
   */
  mainWindow()->guiFactory()->removeClient( this );
}

KateProjectView *KateProjectPluginView::viewForProject (KateProject *project)
{
  /**
   * needs valid project
   */
  Q_ASSERT (project);

  /**
   * existing view?
   */
  if (m_project2View.contains (project))
    return m_project2View.value (project);

  /**
   * create new view
   */
   KateProjectView *view = new KateProjectView (this, project);

   /**
    * attach to toolbox
    */
   m_toolBox->addItem (view, project->name());

   /**
    * remember and return it
    */
   m_project2View[project] = view;
   return view;
}

void KateProjectPluginView::readSessionConfig( KConfigBase* config, const QString& groupPrefix )
{
  // If you have session-dependant settings, load them here.
  // If you have application wide settings, you have to read your own KConfig,
  // see the Kate::Plugin docs for more information.
  Q_UNUSED( config );
  Q_UNUSED( groupPrefix );
}

void KateProjectPluginView::writeSessionConfig( KConfigBase* config, const QString& groupPrefix )
{
  // If you have session-dependant settings, save them here.
  // If you have application wide settings, you have to create your own KConfig,
  // see the Kate::Plugin docs for more information.
  Q_UNUSED( config );
  Q_UNUSED( groupPrefix );
}

QString KateProjectPluginView::projectFileName ()
{
  QWidget *active = m_toolBox->currentWidget ();
  if (!active)
    return QString ();

  return static_cast<KateProjectView *> (active)->project()->fileName ();
}

QStringList KateProjectPluginView::projectFiles ()
{
  KateProjectView *active = static_cast<KateProjectView *> (m_toolBox->currentWidget ());
  if (!active)
    return QStringList ();

  return active->project()->files ();
}

void KateProjectPluginView::slotViewChanged ()
{
  /**
   * get active view
   */
  KTextEditor::View *activeView = mainWindow()->activeView ();

  /**
   * update pointer, maybe disconnect before
   */
  if (m_activeTextEditorView)
    m_activeTextEditorView->document()->disconnect (this);
  m_activeTextEditorView = activeView;

  /**
   * no current active view, return
   */
  if (!m_activeTextEditorView)
    return;

  /**
   * connect to url changed, for auto load
   */
  connect (m_activeTextEditorView->document(), SIGNAL(documentUrlChanged (KTextEditor::Document *)), this, SLOT(slotDocumentUrlChanged (KTextEditor::Document *)));

  /**
   * trigger slot once
   */
  slotDocumentUrlChanged (m_activeTextEditorView->document());
}

void KateProjectPluginView::slotCurrentChanged (int)
{
  /**
   * project file name might have changed
   */
  emit projectFileNameChanged ();
}

void KateProjectPluginView::slotDocumentUrlChanged (KTextEditor::Document *document)
{
  /**
   * abort if empty url or no local path
   */
  if (document->url().isEmpty() || !document->url().isLocalFile())
    return;

  /**
   * search matching project
   */
  KateProject *project = m_plugin->projectForUrl (document->url());
  if (!project)
    return;

  /**
   * get active project view and switch it, if it is for a different project
   */
  KateProjectView *active = static_cast<KateProjectView *> (m_toolBox->currentWidget ());
  if (active != m_project2View.value (project))
      m_toolBox->setCurrentWidget (m_project2View.value (project));

  /**
   * get local filename and then select it
   */
  active->selectFile (document->url().toLocalFile ());
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>


<commit_before>/*----------------------------------------------------------------------------

  LSD - Line Segment Detector on digital images

  Copyright (c) 2007-2011 rafael grompone von gioi <grompone@gmail.com>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as
  published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License
  along with this program. If not, see <http://www.gnu.org/licenses/>.

  ----------------------------------------------------------------------------*/

/// HEADER
#include "lsd.h"

/// PROJECT
#include <csapex/utility/register_apex_plugin.h>
#include <csapex/msg/input.h>
#include <csapex/msg/output.h>
#include <utils_param/parameter_factory.h>
#include <csapex_vision/cv_mat_message.h>
#include <csapex_core_plugins/vector_message.h>
#include <csapex/model/node_modifier.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>

using namespace csapex;
using namespace csapex::connection_types;
using namespace vision_plugins;

CSAPEX_REGISTER_CLASS(vision_plugins::LineSegmentDetector, csapex::Node)

LineSegmentDetector::LineSegmentDetector()
{
}

void LineSegmentDetector::process()
{
    connection_types::CvMatMessage::Ptr a = input_->getMessage<connection_types::CvMatMessage>();

//    cv::Mat image_cv = a->value;

//    X = image_cv.rows;
//    Y = image.cv.cols;
//    /* get memory */

//    image = new double [X*Y];
//    if( image == NULL ) throw std::runtime_error("unsupported norm type");

//    if(Image.type() == CV_8UC3) {
//          Reading_image_impl<cv::Vec1b, Norm>(Image, Distance, Direction, Interpolation_coeff);
//      } else if (Image.type() == CV_32FC3) {
//          Reading_image_impl<cv::Vec1f, Norm>(Image, Distance, Direction, Interpolation_coeff);
//      } else if (Image.type() == CV_64FC3) {
//          Reading_image_impl<cv::Vec1d, Norm>(Image, Distance, Direction, Interpolation_coeff);
//      } else {
//          throw std::runtime_error("unsupported image type");
//      }

////  template <typename PixelType, template<typename> class Norm>
////  void color_edge_detection::RCMG_computation_impl(cv::Mat Image, cv::Mat Distance, cv::Mat Direction, cv::Mat Interpolation_coeff)
////  {
///* read data */
//for(int y=0;y<Y;y++)
//  for(int x=0;x<X;x++)
//    image[ x + y * X ] = (double) image_cv.at<image_cv.type()>(x,y);
}

void LineSegmentDetector::setup()
{
    input_ = modifier_->addInput<connection_types::CvMatMessage>("Image");

    output_ = modifier_->addOutput<connection_types::CvMatMessage>("Image");
}

<commit_msg>io.h included<commit_after>/*----------------------------------------------------------------------------

  LSD - Line Segment Detector on digital images

  Copyright (c) 2007-2011 rafael grompone von gioi <grompone@gmail.com>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as
  published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License
  along with this program. If not, see <http://www.gnu.org/licenses/>.

  ----------------------------------------------------------------------------*/

/// HEADER
#include "lsd.h"

/// PROJECT
#include <csapex/utility/register_apex_plugin.h>
#include <csapex/msg/io.h>
#include <utils_param/parameter_factory.h>
#include <csapex_vision/cv_mat_message.h>
#include <csapex_core_plugins/vector_message.h>
#include <csapex/model/node_modifier.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>

using namespace csapex;
using namespace csapex::connection_types;
using namespace vision_plugins;

CSAPEX_REGISTER_CLASS(vision_plugins::LineSegmentDetector, csapex::Node)

LineSegmentDetector::LineSegmentDetector()
{
}

void LineSegmentDetector::process()
{
    connection_types::CvMatMessage::ConstPtr a = msg::getMessage<connection_types::CvMatMessage>(input_);

//    cv::Mat image_cv = a->value;

//    X = image_cv.rows;
//    Y = image.cv.cols;
//    /* get memory */

//    image = new double [X*Y];
//    if( image == NULL ) throw std::runtime_error("unsupported norm type");

//    if(Image.type() == CV_8UC3) {
//          Reading_image_impl<cv::Vec1b, Norm>(Image, Distance, Direction, Interpolation_coeff);
//      } else if (Image.type() == CV_32FC3) {
//          Reading_image_impl<cv::Vec1f, Norm>(Image, Distance, Direction, Interpolation_coeff);
//      } else if (Image.type() == CV_64FC3) {
//          Reading_image_impl<cv::Vec1d, Norm>(Image, Distance, Direction, Interpolation_coeff);
//      } else {
//          throw std::runtime_error("unsupported image type");
//      }

////  template <typename PixelType, template<typename> class Norm>
////  void color_edge_detection::RCMG_computation_impl(cv::Mat Image, cv::Mat Distance, cv::Mat Direction, cv::Mat Interpolation_coeff)
////  {
///* read data */
//for(int y=0;y<Y;y++)
//  for(int x=0;x<X;x++)
//    image[ x + y * X ] = (double) image_cv.at<image_cv.type()>(x,y);
}

void LineSegmentDetector::setup()
{
    input_ = modifier_->addInput<connection_types::CvMatMessage>("Image");

    output_ = modifier_->addOutput<connection_types::CvMatMessage>("Image");
}

<|endoftext|>


<commit_before>#ifndef VME_HARDWARE_INCLUDE_COMMON_BASE_HH_
#define VME_HARDWARE_INCLUDE_COMMON_BASE_HH_

/*===========================================================================*\

  author: Matthias W. Smith
  email:  mwsmith2@uw.edu
  file:   common_base.hh

  about:  Creates a virtual base class for all hw classes to inherit from.
         Implements a logging scheme.

\*===========================================================================*/

//--- std includes ----------------------------------------------------------//
#include <ctime>
#include <string>
#include <fstream>
#include <iomanip>
#include <cstring>
#include <cstdarg>
#include <mutex>

//--- project includes ------------------------------------------------------//

namespace hw {

class CommonBase {

 public:

  // Ctor params:
  //   name - used in logging output
  CommonBase(std::string name) : name_(name) {};
  ~CommonBase() {};

  inline void SetName(std::string name) { name_ = name; };
  inline void SetLogfile(std::string logfile) { logfile_ = logfile; };
  inline void SetVerbosity(int v) { logging_verbosity_ = v; };

 protected:

  static const int name_width_ = 15;

  // These should be defined in common_extdef.hh
  static int logging_verbosity_;
  static std::string logfile_;
  static std::fstream logstream_;
  static std::mutex log_mutex_;

  std::string name_; // given class(hardware) name
  char logstr_[512];
  time_t timer_;

  // Printf style logging function (for max verbosity).
  inline int LogDump(const char *format, ...) {

    if (logging_verbosity_ > 3) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::DUMP);

      va_list args;
      va_start(args, format);
      vsprintf(logstr_, format, args);
      va_end(args);

      logstream_ << logstr_ << std::endl;
      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Prints a simple string to the log file (for max verbosity).
  inline int LogDump(const std::string& message) {

    if (logging_verbosity_ > 3) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::DUMP);

      logstream_ << message << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Printf style logging function (for debug verbosity).
  inline int LogDebug(const char *format, ...) {

    if (logging_verbosity_ > 2) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::DEBUG);

      va_list args;
      va_start(args, format);
      vsprintf(logstr_, format, args);
      va_end(args);

      logstream_ << logstr_ << std::endl;
      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Prints a simple string to the log file (for debug verbosity).
  inline int LogDebug(const std::string& message) {

    if (logging_verbosity_ > 2) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::DEBUG);

      logstream_ << message << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Printf style logging function (verbosity = 2).
  inline int LogMessage(const char *format, ...) {

    if (logging_verbosity_ > 1) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::MESSAGE);

      va_list args;
      va_start(args, format);
      vsprintf(logstr_, format, args);
      va_end(args);

      logstream_ << logstr_ << std::endl;
      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Prints string to log file (verbosity = 2).
  inline int LogMessage(const std::string& message) {

    if (logging_verbosity_ > 1) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::MESSAGE);

      logstream_ << message << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Printf style logging function (verbosity = 1).
  inline int LogWarning(const char *format, ...) {

    if (logging_verbosity_ > 0) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::WARNING);

      va_list args;
      va_start(args, format);
      vsprintf(logstr_, format, args);
      va_end(args);

      logstream_ << logstr_ << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Prints string to log file (verbosity = 1).
  inline int LogWarning(const std::string& warning) {

    if (logging_verbosity_ > 0) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::WARNING);

      logstream_ << warning << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Printf style logging function (always).
  inline int LogError(const char *format, ...) {

    log_mutex_.lock();

    while (!logstream_.is_open()) {
      logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
    }

    prepend(level::ERROR);

    va_list args;
    va_start(args, format);
    vsprintf(logstr_, format, args);
    va_end(args);

    logstream_ << logstr_ << std::endl;

    logstream_.close();
    log_mutex_.unlock();

    return 0;
  };

  // Prints string to log file (always).
  inline int LogError(const std::string& error) {

    log_mutex_.lock();

    while (!logstream_.is_open()) {
      logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
    }

    prepend(level::ERROR);

    logstream_ << error << std::endl;

    logstream_.close();
    log_mutex_.unlock();

    return 0;
  };

  // User to override the default log file (/var/log/lab-hw/fast-hw.log).
  void SetLogFile(const std::string& logfile) {
    log_mutex_.lock();
    logfile_ = logfile;
    log_mutex_.unlock();
  };

 private:

  enum level { DUMP, DEBUG, MESSAGE, WARNING, ERROR };

  inline void prepend(level lvl) {

    static timespec t;
    static char tm_start[100];
    static std::string lvl_msg;

    clock_gettime(CLOCK_REALTIME, &t);
    std::strftime(tm_start, sizeof(tm_start), "[%F %T.", localtime(&t.tv_sec));

    switch (lvl) {
      case DUMP:
        lvl_msg = std::string("]  ==DUMP== ");
        break;
      case DEBUG:
        lvl_msg = std::string("]  =DEBUG=  ");
        break;
      case MESSAGE:
        lvl_msg = std::string("]  MESSAGE  ");
        break;
      case WARNING:
        lvl_msg = std::string("] *WARNING* ");
        break;
      case ERROR:
        lvl_msg = std::string("] **ERROR** ");
        break;
    }

    logstream_ << tm_start << std::right << std::setfill('0') << std::setw(6);
    logstream_ << t.tv_nsec / 1000 << lvl_msg << std::setfill(' ') << "{ ";
    logstream_ << std::left << std::setw(name_width_) << name_ << " } : ";
  }
};

} // hw

#endif
<commit_msg>Normalizes logfile setter.<commit_after>#ifndef VME_HARDWARE_INCLUDE_COMMON_BASE_HH_
#define VME_HARDWARE_INCLUDE_COMMON_BASE_HH_

/*===========================================================================*\

  author: Matthias W. Smith
  email:  mwsmith2@uw.edu
  file:   common_base.hh

  about:  Creates a virtual base class for all hw classes to inherit from.
         Implements a logging scheme.

\*===========================================================================*/

//--- std includes ----------------------------------------------------------//
#include <ctime>
#include <string>
#include <fstream>
#include <iomanip>
#include <cstring>
#include <cstdarg>
#include <mutex>

//--- project includes ------------------------------------------------------//

namespace hw {

class CommonBase {

 public:

  // Ctor params:
  //   name - used in logging output
  CommonBase(std::string name) : name_(name) {};
  ~CommonBase() {};

  inline void SetName(std::string name) { name_ = name; };
  inline void SetVerbosity(int v) { logging_verbosity_ = v; };

 protected:

  static const int name_width_ = 15;

  // These should be defined in common_extdef.hh
  static int logging_verbosity_;
  static std::string logfile_;
  static std::fstream logstream_;
  static std::mutex log_mutex_;

  std::string name_; // given class(hardware) name
  char logstr_[512];
  time_t timer_;

  // Printf style logging function (for max verbosity).
  inline int LogDump(const char *format, ...) {

    if (logging_verbosity_ > 3) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::DUMP);

      va_list args;
      va_start(args, format);
      vsprintf(logstr_, format, args);
      va_end(args);

      logstream_ << logstr_ << std::endl;
      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Prints a simple string to the log file (for max verbosity).
  inline int LogDump(const std::string& message) {

    if (logging_verbosity_ > 3) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::DUMP);

      logstream_ << message << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Printf style logging function (for debug verbosity).
  inline int LogDebug(const char *format, ...) {

    if (logging_verbosity_ > 2) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::DEBUG);

      va_list args;
      va_start(args, format);
      vsprintf(logstr_, format, args);
      va_end(args);

      logstream_ << logstr_ << std::endl;
      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Prints a simple string to the log file (for debug verbosity).
  inline int LogDebug(const std::string& message) {

    if (logging_verbosity_ > 2) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::DEBUG);

      logstream_ << message << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Printf style logging function (verbosity = 2).
  inline int LogMessage(const char *format, ...) {

    if (logging_verbosity_ > 1) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::MESSAGE);

      va_list args;
      va_start(args, format);
      vsprintf(logstr_, format, args);
      va_end(args);

      logstream_ << logstr_ << std::endl;
      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Prints string to log file (verbosity = 2).
  inline int LogMessage(const std::string& message) {

    if (logging_verbosity_ > 1) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::MESSAGE);

      logstream_ << message << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Printf style logging function (verbosity = 1).
  inline int LogWarning(const char *format, ...) {

    if (logging_verbosity_ > 0) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::WARNING);

      va_list args;
      va_start(args, format);
      vsprintf(logstr_, format, args);
      va_end(args);

      logstream_ << logstr_ << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Prints string to log file (verbosity = 1).
  inline int LogWarning(const std::string& warning) {

    if (logging_verbosity_ > 0) {
      log_mutex_.lock();

      while (!logstream_.is_open()) {
        logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
      }

      prepend(level::WARNING);

      logstream_ << warning << std::endl;

      logstream_.close();
      log_mutex_.unlock();
    }

    return 0;
  };

  // Printf style logging function (always).
  inline int LogError(const char *format, ...) {

    log_mutex_.lock();

    while (!logstream_.is_open()) {
      logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
    }

    prepend(level::ERROR);

    va_list args;
    va_start(args, format);
    vsprintf(logstr_, format, args);
    va_end(args);

    logstream_ << logstr_ << std::endl;

    logstream_.close();
    log_mutex_.unlock();

    return 0;
  };

  // Prints string to log file (always).
  inline int LogError(const std::string& error) {

    log_mutex_.lock();

    while (!logstream_.is_open()) {
      logstream_.open(logfile_, std::fstream::app | std::fstream::out);
        usleep(10);
    }

    prepend(level::ERROR);

    logstream_ << error << std::endl;

    logstream_.close();
    log_mutex_.unlock();

    return 0;
  };

  // User to override the default log file (/usr/local/var/log/g2field/vme-hw.log).
  void SetLogfile(const std::string& logfile) {
    log_mutex_.lock();
    logfile_ = logfile;
    log_mutex_.unlock();
  };

 private:

  enum level { DUMP, DEBUG, MESSAGE, WARNING, ERROR };

  inline void prepend(level lvl) {

    static timespec t;
    static char tm_start[100];
    static std::string lvl_msg;

    clock_gettime(CLOCK_REALTIME, &t);
    std::strftime(tm_start, sizeof(tm_start), "[%F %T.", localtime(&t.tv_sec));

    switch (lvl) {
      case DUMP:
        lvl_msg = std::string("]  ==DUMP== ");
        break;
      case DEBUG:
        lvl_msg = std::string("]  =DEBUG=  ");
        break;
      case MESSAGE:
        lvl_msg = std::string("]  MESSAGE  ");
        break;
      case WARNING:
        lvl_msg = std::string("] *WARNING* ");
        break;
      case ERROR:
        lvl_msg = std::string("] **ERROR** ");
        break;
    }

    logstream_ << tm_start << std::right << std::setfill('0') << std::setw(6);
    logstream_ << t.tv_nsec / 1000 << lvl_msg << std::setfill(' ') << "{ ";
    logstream_ << std::left << std::setw(name_width_) << name_ << " } : ";
  }
};

} // hw

#endif
<|endoftext|>


<commit_before>#include "ntp1script_issuance.h"

#include "base58.h"
#include "hash.h"
#include "util.h"
#include <boost/algorithm/hex.hpp>

std::string NTP1Script_Issuance::__getAggregAndLockStatusTokenIDHexValue() const
{
    std::string aggregatableHex;
    if (isLocked()) {
        if (getAggregationPolicy() == IssuanceFlags::AggregationPolicy::AggregationPolicy_Aggregatable) {
            aggregatableHex = "20ce";
        } else if (getAggregationPolicy() ==
                   IssuanceFlags::AggregationPolicy::AggregationPolicy_NonAggregatable) {
            aggregatableHex = "20e4";
        } else {
            throw std::runtime_error("Unknown aggregation policity for token: " + getTokenSymbol());
        }
    } else {
        if (getAggregationPolicy() == IssuanceFlags::AggregationPolicy::AggregationPolicy_Aggregatable) {
            aggregatableHex = "2e37";
        } else if (getAggregationPolicy() ==
                   IssuanceFlags::AggregationPolicy::AggregationPolicy_NonAggregatable) {
            aggregatableHex = "2e4e";
        } else {
            throw std::runtime_error("Unknown aggregation policity for token: " + getTokenSymbol());
        }
    }
    return aggregatableHex;
}

NTP1Script_Issuance::NTP1Script_Issuance() {}

std::string NTP1Script_Issuance::getHexMetadata() const { return boost::algorithm::hex(metadata); }

std::string NTP1Script_Issuance::getRawMetadata() const { return metadata; }

int NTP1Script_Issuance::getDivisibility() const { return issuanceFlags.divisibility; }

bool NTP1Script_Issuance::isLocked() const { return issuanceFlags.locked; }

NTP1Script::IssuanceFlags::AggregationPolicy NTP1Script_Issuance::getAggregationPolicy() const
{
    return issuanceFlags.aggregationPolicy;
}

std::string NTP1Script_Issuance::getAggregationPolicyStr() const
{
    if (issuanceFlags.aggregationPolicy == NTP1Script::IssuanceFlags::AggregationPolicy_Aggregatable) {
        return IssuanceFlags::AggregationPolicy_Aggregatable_Str;
    } else if (issuanceFlags.aggregationPolicy ==
               NTP1Script::IssuanceFlags::AggregationPolicy_Aggregatable) {
        return IssuanceFlags::AggregationPolicy_NonAggregatable_Str;
    } else {
        return IssuanceFlags::AggregationPolicy_Aggregatable_Str;
    }
}

std::string NTP1Script_Issuance::getTokenSymbol() const { return tokenSymbol; }

NTP1Int NTP1Script_Issuance::getAmount() const { return amount; }

unsigned NTP1Script_Issuance::getTransferInstructionsCount() const
{
    return transferInstructions.size();
}

NTP1Script::TransferInstruction NTP1Script_Issuance::getTransferInstruction(unsigned index) const
{
    return transferInstructions[index];
}

std::vector<NTP1Script::TransferInstruction> NTP1Script_Issuance::getTransferInstructions() const
{
    return transferInstructions;
}

std::shared_ptr<NTP1Script_Issuance>
NTP1Script_Issuance::ParseIssuancePostHeaderData(std::string ScriptBin, std::string OpCodeBin)
{
    std::shared_ptr<NTP1Script_Issuance> result = std::make_shared<NTP1Script_Issuance>();

    // get token symbol (size always = 5 bytes)
    result->tokenSymbol = ParseTokenSymbolFromLongEnoughString(ScriptBin);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + 5);

    // get metadata then drop it
    result->metadata = ParseMetadataFromLongEnoughString(ScriptBin, OpCodeBin);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + result->metadata.size());

    // parse amount
    int amountRawSize = 0;
    result->amount    = ParseAmountFromLongEnoughString(ScriptBin, amountRawSize);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + amountRawSize);

    // parse transfer instructions
    int totalTransferInstructionsSize = 0;
    result->transferInstructions =
        ParseTransferInstructionsFromLongEnoughString(ScriptBin, totalTransferInstructionsSize);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + totalTransferInstructionsSize);

    // check that no skip transfer instructions exist; as it's forbidden in issuance
    for (const auto& inst : result->transferInstructions) {
        if (inst.skipInput) {
            throw std::runtime_error("An issuance script contained a skip transfer instruction: " +
                                     boost::algorithm::hex(ScriptBin));
        }
    }

    // the expected remaining byte is the issuance flag, otherwise a problem is there
    if (ScriptBin.size() != 1) {
        throw std::runtime_error(
            "Last expected byte is the issuance flag, but the remaining bytes are: " +
            boost::algorithm::hex(ScriptBin) + ", starting from " + boost::algorithm::hex(ScriptBin));
    }

    result->issuanceFlags = IssuanceFlags::ParseIssuanceFlag(ScriptBin.at(0));
    return result;
}

std::shared_ptr<NTP1Script_Issuance>
NTP1Script_Issuance::ParseNTP1v3IssuancePostHeaderData(std::string ScriptBin)
{
    std::shared_ptr<NTP1Script_Issuance> result = std::make_shared<NTP1Script_Issuance>();

    // get token symbol (size always = 5 bytes)
    result->tokenSymbol = ParseTokenSymbolFromLongEnoughString(ScriptBin);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + 5);

    // parse amount
    int amountRawSize = 0;
    result->amount    = ParseAmountFromLongEnoughString(ScriptBin, amountRawSize);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + amountRawSize);

    // parse transfer instructions
    int totalTransferInstructionsSize = 0;
    result->transferInstructions =
        ParseNTP1v3TransferInstructionsFromLongEnoughString(ScriptBin, totalTransferInstructionsSize);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + totalTransferInstructionsSize);

    // check that no skip transfer instructions exist; as it's forbidden in issuance
    for (const auto& inst : result->transferInstructions) {
        if (inst.skipInput) {
            throw std::runtime_error("An issuance script contained a skip transfer instruction: " +
                                     boost::algorithm::hex(ScriptBin));
        }
    }

    // remaining is 1 byte for issuance flag and 4 for metadata start flag + the metadata itself
    if (ScriptBin.size() < 1) {
        throw std::runtime_error("The data remaining cannot fit the issuance flags, which is 1 byte: " +
                                 boost::algorithm::hex(ScriptBin) + ", starting from " +
                                 boost::algorithm::hex(ScriptBin));
    }

    result->issuanceFlags = IssuanceFlags::ParseIssuanceFlag(ScriptBin.at(0));
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + 1);

    result->metadata = ParseNTP1v3MetadataFromLongEnoughString(ScriptBin);
    if (result->metadata.size() > 0) {
        ScriptBin.erase(ScriptBin.begin(),
                        ScriptBin.begin() + result->metadata.size() + 4); // + 4 for size
    }

    if (ScriptBin.size() != 0) {
        throw std::runtime_error("Garbage data after the metadata (unaccounted for in size).");
    }

    return result;
}

std::string NTP1Script_Issuance::getTokenID(std::string input0txid, unsigned int input0index) const
{
    // txid should be lower case
    std::transform(input0txid.begin(), input0txid.end(), input0txid.begin(), ::tolower);

    std::string tohash = input0txid + ":" + std::to_string(input0index);

    std::vector<unsigned char> sha256_result(32);
    std::vector<unsigned char> rip160_result(20);
    SHA256(reinterpret_cast<unsigned char*>(&tohash.front()), tohash.size(), &sha256_result.front());
    RIPEMD160(&sha256_result.front(), sha256_result.size(), &rip160_result.front());

    // get padded divisibility
    std::string divisibilityHex = ToHexString(getDivisibility(), false);
    if (divisibilityHex.size() > 4) {
        throw std::runtime_error("Divisibility hex value has more than 4 digits for token " +
                                 getTokenSymbol());
    }
    divisibilityHex             = std::string(4 - divisibilityHex.size(), '0') + divisibilityHex;
    std::string divisibilityBin = boost::algorithm::unhex(divisibilityHex);

    // aggregation policy and lock status
    std::string aggregatableHex = __getAggregAndLockStatusTokenIDHexValue();
    std::string aggregatableBin = boost::algorithm::unhex(aggregatableHex);

    std::vector<unsigned char> toBase58Check;
    toBase58Check.insert(toBase58Check.end(), aggregatableBin.begin(), aggregatableBin.end());
    toBase58Check.insert(toBase58Check.end(), rip160_result.begin(), rip160_result.end());
    toBase58Check.insert(toBase58Check.end(), divisibilityBin.begin(), divisibilityBin.end());

    std::string result = EncodeBase58Check(toBase58Check);

    return result;
}

std::string NTP1Script_Issuance::calculateScriptBin() const
{
    using namespace boost::algorithm;

    if (protocolVersion == 1) {
        std::string result;
        result += headerBin;
        result += opCodeBin;
        result += Create_ProcessTokenSymbol(tokenSymbol);
        result += metadata;
        result += unhex(NumberToHexNTP1Amount(amount));

        for (const auto& ti : transferInstructions) {
            result += TransferInstructionToBinScript(ti);
        }

        uint8_t issuanceFlagsByte = issuanceFlags.convertToByte();
        result.push_back(*reinterpret_cast<char*>(&issuanceFlagsByte));

        return result;
    } else if (protocolVersion == 3) {
        std::string result;
        result += headerBin;
        result += opCodeBin;
        result += Create_ProcessTokenSymbol(tokenSymbol);

        result += unhex(NumberToHexNTP1Amount(amount));

        unsigned char TIsSize = static_cast<unsigned char>(transferInstructions.size());

        result.push_back(static_cast<char>(TIsSize));

        for (const auto& ti : transferInstructions) {
            result += TransferInstructionToBinScript(ti);
        }

        uint8_t issuanceFlagsByte = issuanceFlags.convertToByte();
        result.push_back(*reinterpret_cast<char*>(&issuanceFlagsByte));

        if (metadata.size() > 0) {
            uint32_t metadataSize = metadata.size();
#ifdef __BYTE_ORDER__
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
            SwapEndianness(metadataSize); // size is big-endian
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#else
            static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__, "Unsupported endianness");
#endif
#endif
            std::string metadataSizeStr;
            metadataSizeStr.resize(4);
            static_assert(sizeof(metadataSize) == 4,
                          "Metadata size must be 4 bytes accoring to NTP1v3 standard");
            memcpy(&metadataSizeStr.front(), &metadataSize, 4);

            result += metadataSizeStr;
            result += metadata;
        }

        return result;

    } else {
        throw std::runtime_error("While creating issuance transcation, unknown protocol version + " +
                                 std::to_string(protocolVersion));
    }
}

std::shared_ptr<NTP1Script_Issuance> NTP1Script_Issuance::CreateScript(
    const std::string& Symbol, uint64_t amount,
    const std::vector<NTP1Script::TransferInstruction>& transferInstructions,
    const std::string& Metadata, bool Locked, unsigned int Divisibility,
    IssuanceFlags::AggregationPolicy AggrPolicy)
{
    std::shared_ptr<NTP1Script_Issuance> script = std::make_shared<NTP1Script_Issuance>();

    script->metadata    = Metadata;
    script->opCodeBin   = boost::algorithm::unhex(std::string("01"));
    script->tokenSymbol = Symbol;
    script->amount      = amount;
    IssuanceFlags issuanceFlags;
    issuanceFlags.aggregationPolicy = AggrPolicy;
    issuanceFlags.divisibility      = static_cast<int>(Divisibility);
    issuanceFlags.locked            = Locked;
    script->transferInstructions    = transferInstructions;
    script->issuanceFlags           = issuanceFlags;
    script->headerBin               = boost::algorithm::unhex(std::string("4e5403"));
    script->protocolVersion         = 3;
    script->txType                  = TxType::TxType_Issuance;

    return script;
}

std::string NTP1Script_Issuance::Create_OpCodeFromMetadata(const std::string& metadata)
{
    const auto& sz = metadata.size();
    std::string result;
    if (sz == 0) {
        return std::string(1, static_cast<char>(uint8_t(0x05)));
    } else if (sz == 20) {
        return std::string(1, static_cast<char>(uint8_t(0x02)));
    } else if (sz == 52) {
        return std::string(1, static_cast<char>(uint8_t(0x01)));
    } else {
        throw std::runtime_error("Invalid metadata size; can only be 0, 20 or 52");
    }
    return boost::algorithm::unhex(result);
}

std::string NTP1Script_Issuance::Create_ProcessTokenSymbol(const std::string& symbol)
{
    if (symbol.size() > 5) {
        throw std::runtime_error("Symbol cannot be more than 5 characters");
    }
    std::string result = symbol;
    while (result.size() < 5) {
        result.push_back(0x20);
    }
    return result;
}

std::set<unsigned int> NTP1Script_Issuance::getNTP1OutputIndices() const
{
    std::set<unsigned int> result;
    for (const auto& ti : transferInstructions) {
        result.insert(ti.outputIndex);
    }
    return result;
}
<commit_msg>Minor<commit_after>#include "ntp1script_issuance.h"

#include "base58.h"
#include "hash.h"
#include "util.h"
#include <boost/algorithm/hex.hpp>

std::string NTP1Script_Issuance::__getAggregAndLockStatusTokenIDHexValue() const
{
    std::string aggregatableHex;
    if (isLocked()) {
        if (getAggregationPolicy() == IssuanceFlags::AggregationPolicy::AggregationPolicy_Aggregatable) {
            aggregatableHex = "20ce";
        } else if (getAggregationPolicy() ==
                   IssuanceFlags::AggregationPolicy::AggregationPolicy_NonAggregatable) {
            aggregatableHex = "20e4";
        } else {
            throw std::runtime_error("Unknown aggregation policity for token: " + getTokenSymbol());
        }
    } else {
        if (getAggregationPolicy() == IssuanceFlags::AggregationPolicy::AggregationPolicy_Aggregatable) {
            aggregatableHex = "2e37";
        } else if (getAggregationPolicy() ==
                   IssuanceFlags::AggregationPolicy::AggregationPolicy_NonAggregatable) {
            aggregatableHex = "2e4e";
        } else {
            throw std::runtime_error("Unknown aggregation policity for token: " + getTokenSymbol());
        }
    }
    return aggregatableHex;
}

NTP1Script_Issuance::NTP1Script_Issuance() {}

std::string NTP1Script_Issuance::getHexMetadata() const { return boost::algorithm::hex(metadata); }

std::string NTP1Script_Issuance::getRawMetadata() const { return metadata; }

int NTP1Script_Issuance::getDivisibility() const { return issuanceFlags.divisibility; }

bool NTP1Script_Issuance::isLocked() const { return issuanceFlags.locked; }

NTP1Script::IssuanceFlags::AggregationPolicy NTP1Script_Issuance::getAggregationPolicy() const
{
    return issuanceFlags.aggregationPolicy;
}

std::string NTP1Script_Issuance::getAggregationPolicyStr() const
{
    if (issuanceFlags.aggregationPolicy == NTP1Script::IssuanceFlags::AggregationPolicy_Aggregatable) {
        return IssuanceFlags::AggregationPolicy_Aggregatable_Str;
    } else if (issuanceFlags.aggregationPolicy ==
               NTP1Script::IssuanceFlags::AggregationPolicy_Aggregatable) {
        return IssuanceFlags::AggregationPolicy_NonAggregatable_Str;
    } else {
        return IssuanceFlags::AggregationPolicy_Aggregatable_Str;
    }
}

std::string NTP1Script_Issuance::getTokenSymbol() const { return tokenSymbol; }

NTP1Int NTP1Script_Issuance::getAmount() const { return amount; }

unsigned NTP1Script_Issuance::getTransferInstructionsCount() const
{
    return transferInstructions.size();
}

NTP1Script::TransferInstruction NTP1Script_Issuance::getTransferInstruction(unsigned index) const
{
    return transferInstructions[index];
}

std::vector<NTP1Script::TransferInstruction> NTP1Script_Issuance::getTransferInstructions() const
{
    return transferInstructions;
}

std::shared_ptr<NTP1Script_Issuance>
NTP1Script_Issuance::ParseIssuancePostHeaderData(std::string ScriptBin, std::string OpCodeBin)
{
    std::shared_ptr<NTP1Script_Issuance> result = std::make_shared<NTP1Script_Issuance>();

    // get token symbol (size always = 5 bytes)
    result->tokenSymbol = ParseTokenSymbolFromLongEnoughString(ScriptBin);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + 5);

    // get metadata then drop it
    result->metadata = ParseMetadataFromLongEnoughString(ScriptBin, OpCodeBin);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + result->metadata.size());

    // parse amount
    int amountRawSize = 0;
    result->amount    = ParseAmountFromLongEnoughString(ScriptBin, amountRawSize);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + amountRawSize);

    // parse transfer instructions
    int totalTransferInstructionsSize = 0;
    result->transferInstructions =
        ParseTransferInstructionsFromLongEnoughString(ScriptBin, totalTransferInstructionsSize);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + totalTransferInstructionsSize);

    // check that no skip transfer instructions exist; as it's forbidden in issuance
    for (const auto& inst : result->transferInstructions) {
        if (inst.skipInput) {
            throw std::runtime_error("An issuance script contained a skip transfer instruction: " +
                                     boost::algorithm::hex(ScriptBin));
        }
    }

    // the expected remaining byte is the issuance flag, otherwise a problem is there
    if (ScriptBin.size() != 1) {
        throw std::runtime_error(
            "Last expected byte is the issuance flag, but the remaining bytes are: " +
            boost::algorithm::hex(ScriptBin) + ", starting from " + boost::algorithm::hex(ScriptBin));
    }

    result->issuanceFlags = IssuanceFlags::ParseIssuanceFlag(ScriptBin.at(0));
    return result;
}

std::shared_ptr<NTP1Script_Issuance>
NTP1Script_Issuance::ParseNTP1v3IssuancePostHeaderData(std::string ScriptBin)
{
    std::shared_ptr<NTP1Script_Issuance> result = std::make_shared<NTP1Script_Issuance>();

    // get token symbol (size always = 5 bytes)
    result->tokenSymbol = ParseTokenSymbolFromLongEnoughString(ScriptBin);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + 5);

    // parse amount
    int amountRawSize = 0;
    result->amount    = ParseAmountFromLongEnoughString(ScriptBin, amountRawSize);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + amountRawSize);

    // parse transfer instructions
    int totalTransferInstructionsSize = 0;
    result->transferInstructions =
        ParseNTP1v3TransferInstructionsFromLongEnoughString(ScriptBin, totalTransferInstructionsSize);
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + totalTransferInstructionsSize);

    // check that no skip transfer instructions exist; as it's forbidden in issuance
    for (const auto& inst : result->transferInstructions) {
        if (inst.skipInput) {
            throw std::runtime_error("An issuance script contained a skip transfer instruction: " +
                                     boost::algorithm::hex(ScriptBin));
        }
    }

    // remaining is 1 byte for issuance flag and 4 for metadata start flag + the metadata itself
    if (ScriptBin.size() < 1) {
        throw std::runtime_error("The data remaining cannot fit the issuance flags. It is empty.");
    }

    result->issuanceFlags = IssuanceFlags::ParseIssuanceFlag(ScriptBin.at(0));
    ScriptBin.erase(ScriptBin.begin(), ScriptBin.begin() + 1);

    result->metadata = ParseNTP1v3MetadataFromLongEnoughString(ScriptBin);
    if (result->metadata.size() > 0) {
        ScriptBin.erase(ScriptBin.begin(),
                        ScriptBin.begin() + result->metadata.size() + 4); // + 4 for size
    }

    if (ScriptBin.size() != 0) {
        throw std::runtime_error("Garbage data after the metadata (unaccounted for in size).");
    }

    return result;
}

std::string NTP1Script_Issuance::getTokenID(std::string input0txid, unsigned int input0index) const
{
    // txid should be lower case
    std::transform(input0txid.begin(), input0txid.end(), input0txid.begin(), ::tolower);

    std::string tohash = input0txid + ":" + std::to_string(input0index);

    std::vector<unsigned char> sha256_result(32);
    std::vector<unsigned char> rip160_result(20);
    SHA256(reinterpret_cast<unsigned char*>(&tohash.front()), tohash.size(), &sha256_result.front());
    RIPEMD160(&sha256_result.front(), sha256_result.size(), &rip160_result.front());

    // get padded divisibility
    std::string divisibilityHex = ToHexString(getDivisibility(), false);
    if (divisibilityHex.size() > 4) {
        throw std::runtime_error("Divisibility hex value has more than 4 digits for token " +
                                 getTokenSymbol());
    }
    divisibilityHex             = std::string(4 - divisibilityHex.size(), '0') + divisibilityHex;
    std::string divisibilityBin = boost::algorithm::unhex(divisibilityHex);

    // aggregation policy and lock status
    std::string aggregatableHex = __getAggregAndLockStatusTokenIDHexValue();
    std::string aggregatableBin = boost::algorithm::unhex(aggregatableHex);

    std::vector<unsigned char> toBase58Check;
    toBase58Check.insert(toBase58Check.end(), aggregatableBin.begin(), aggregatableBin.end());
    toBase58Check.insert(toBase58Check.end(), rip160_result.begin(), rip160_result.end());
    toBase58Check.insert(toBase58Check.end(), divisibilityBin.begin(), divisibilityBin.end());

    std::string result = EncodeBase58Check(toBase58Check);

    return result;
}

std::string NTP1Script_Issuance::calculateScriptBin() const
{
    using namespace boost::algorithm;

    if (protocolVersion == 1) {
        std::string result;
        result += headerBin;
        result += opCodeBin;
        result += Create_ProcessTokenSymbol(tokenSymbol);
        result += metadata;
        result += unhex(NumberToHexNTP1Amount(amount));

        for (const auto& ti : transferInstructions) {
            result += TransferInstructionToBinScript(ti);
        }

        uint8_t issuanceFlagsByte = issuanceFlags.convertToByte();
        result.push_back(*reinterpret_cast<char*>(&issuanceFlagsByte));

        return result;
    } else if (protocolVersion == 3) {
        std::string result;
        result += headerBin;
        result += opCodeBin;
        result += Create_ProcessTokenSymbol(tokenSymbol);

        result += unhex(NumberToHexNTP1Amount(amount));

        unsigned char TIsSize = static_cast<unsigned char>(transferInstructions.size());

        result.push_back(static_cast<char>(TIsSize));

        for (const auto& ti : transferInstructions) {
            result += TransferInstructionToBinScript(ti);
        }

        uint8_t issuanceFlagsByte = issuanceFlags.convertToByte();
        result.push_back(*reinterpret_cast<char*>(&issuanceFlagsByte));

        if (metadata.size() > 0) {
            uint32_t metadataSize = metadata.size();
#ifdef __BYTE_ORDER__
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
            SwapEndianness(metadataSize); // size is big-endian
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#else
            static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__, "Unsupported endianness");
#endif
#endif
            std::string metadataSizeStr;
            metadataSizeStr.resize(4);
            static_assert(sizeof(metadataSize) == 4,
                          "Metadata size must be 4 bytes accoring to NTP1v3 standard");
            memcpy(&metadataSizeStr.front(), &metadataSize, 4);

            result += metadataSizeStr;
            result += metadata;
        }

        return result;

    } else {
        throw std::runtime_error("While creating issuance transcation, unknown protocol version + " +
                                 std::to_string(protocolVersion));
    }
}

std::shared_ptr<NTP1Script_Issuance> NTP1Script_Issuance::CreateScript(
    const std::string& Symbol, uint64_t amount,
    const std::vector<NTP1Script::TransferInstruction>& transferInstructions,
    const std::string& Metadata, bool Locked, unsigned int Divisibility,
    IssuanceFlags::AggregationPolicy AggrPolicy)
{
    std::shared_ptr<NTP1Script_Issuance> script = std::make_shared<NTP1Script_Issuance>();

    script->metadata    = Metadata;
    script->opCodeBin   = boost::algorithm::unhex(std::string("01"));
    script->tokenSymbol = Symbol;
    script->amount      = amount;
    IssuanceFlags issuanceFlags;
    issuanceFlags.aggregationPolicy = AggrPolicy;
    issuanceFlags.divisibility      = static_cast<int>(Divisibility);
    issuanceFlags.locked            = Locked;
    script->transferInstructions    = transferInstructions;
    script->issuanceFlags           = issuanceFlags;
    script->headerBin               = boost::algorithm::unhex(std::string("4e5403"));
    script->protocolVersion         = 3;
    script->txType                  = TxType::TxType_Issuance;

    return script;
}

std::string NTP1Script_Issuance::Create_OpCodeFromMetadata(const std::string& metadata)
{
    const auto& sz = metadata.size();
    std::string result;
    if (sz == 0) {
        return std::string(1, static_cast<char>(uint8_t(0x05)));
    } else if (sz == 20) {
        return std::string(1, static_cast<char>(uint8_t(0x02)));
    } else if (sz == 52) {
        return std::string(1, static_cast<char>(uint8_t(0x01)));
    } else {
        throw std::runtime_error("Invalid metadata size; can only be 0, 20 or 52");
    }
    return boost::algorithm::unhex(result);
}

std::string NTP1Script_Issuance::Create_ProcessTokenSymbol(const std::string& symbol)
{
    if (symbol.size() > 5) {
        throw std::runtime_error("Symbol cannot be more than 5 characters");
    }
    std::string result = symbol;
    while (result.size() < 5) {
        result.push_back(0x20);
    }
    return result;
}

std::set<unsigned int> NTP1Script_Issuance::getNTP1OutputIndices() const
{
    std::set<unsigned int> result;
    for (const auto& ti : transferInstructions) {
        result.insert(ti.outputIndex);
    }
    return result;
}
<|endoftext|>


<commit_before>#include <memory>
#include <tuple>
#include <type_traits>

#define IMPLEMENT_ME std::terminate();

namespace archie {
namespace utils {
  namespace containers {
    template <typename Tp, typename Alloc = std::allocator<Tp>>
    struct dynamic_array {
      using allocator_type = Alloc;
      using pointer = typename allocator_type::pointer;
      using const_pointer = typename allocator_type::const_pointer;
      using value_type = typename allocator_type::value_type;
      using reference = typename allocator_type::reference;
      using const_reference = typename allocator_type::const_reference;
      using size_type = typename allocator_type::size_type;
      using difference_type = typename allocator_type::difference_type;

      using iterator = __gnu_cxx::__normal_iterator<pointer, dynamic_array>;
      using const_iterator = __gnu_cxx::__normal_iterator<const_pointer, dynamic_array>;
      using reverse_iterator = std::reverse_iterator<iterator>;
      using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    private:
      using tp_alloc = typename allocator_type::template rebind<Tp>::other;
      struct impl : private tp_alloc {
        using tp_alloc::allocate;
        using tp_alloc::deallocate;
        using tp_alloc::construct;
        using tp_alloc::destroy;

        pointer start_ = nullptr;
        pointer finish_ = nullptr;
        pointer end_of_storage_ = nullptr;

        impl() noexcept = default;

        explicit impl(tp_alloc const& a) noexcept : tp_alloc(a),
                                                    start_(nullptr),
                                                    finish_(nullptr),
                                                    end_of_storage_(nullptr) {}

        void create_storage(size_type n) {
          if (n != size_type(end_of_storage_ - start_)) {
            start_ = (n != 0u) ? allocate(n) : nullptr;
            finish_ = start_;
            end_of_storage_ = start_ + n;
          }
        }

        void destroy_storage() noexcept {
          deallocate(start_, end_of_storage_ - start_);
          start_ = nullptr;
          finish_ = nullptr;
          end_of_storage_ = nullptr;
        }

        tp_alloc& get_allocator() noexcept { return static_cast<tp_alloc&>(*this); }

        tp_alloc const& get_allocator() const noexcept {
          return static_cast<tp_alloc const&>(*this);
        }

        void swap(impl& x) noexcept {
          std::swap(start_, x.start_);
          std::swap(finish_, x.finish_);
          std::swap(end_of_storage_, x.end_of_storage_);
          std::swap(get_allocator(), x.get_allocator());
        }
      };

      impl impl_;

    public:
      dynamic_array() = default;

      explicit dynamic_array(size_type n) { impl_.create_storage(n); }

      dynamic_array(size_type n, allocator_type const& a) : impl_(a) { impl_.create_storage(n); }

      dynamic_array(dynamic_array&& x) noexcept { impl_.swap(x.impl_); }

      dynamic_array& operator=(dynamic_array&& x) noexcept {
        clear();
        if (capacity() != 0u) impl_.destroy_storage();
        impl_.swap(x.impl_);
        return *this;
      }

      dynamic_array(dynamic_array const&) { IMPLEMENT_ME }

      dynamic_array& operator=(dynamic_array const&) {
        IMPLEMENT_ME
        return *this;
      }

      dynamic_array(std::initializer_list<value_type>) { IMPLEMENT_ME }

      dynamic_array& operator=(std::initializer_list<value_type>) {
        IMPLEMENT_ME
        return *this;
      }

      template <typename InputIterator>
      dynamic_array(InputIterator, InputIterator) {
        IMPLEMENT_ME
      }

      ~dynamic_array() noexcept {
        clear();
        if (capacity() != 0u) impl_.destroy_storage();
      }

      size_type capacity() const noexcept {
        return size_type(impl_.end_of_storage_ - impl_.start_);
      }

      size_type size() const noexcept { return size_type(impl_.finish_ - impl_.start_); }

      bool empty() const noexcept { return cbegin() == cend(); }

      bool full() const noexcept { return impl_.finish_ == impl_.end_of_storage_; }

      template <typename... Args>
      void emplace_back(Args&&... args) noexcept(
          std::is_nothrow_constructible<value_type, Args...>::value) {
        impl_.construct(impl_.finish_, std::forward<Args>(args)...);
        ++impl_.finish_;
      }

      void push_back(const_reference x) noexcept(
          std::is_nothrow_copy_constructible<value_type>::value) {
        emplace_back(x);
      }

      void push_back(value_type&& x) noexcept(
          std::is_nothrow_move_constructible<value_type>::value) {
        emplace_back(std::move(x));
      }

      void pop_back() noexcept { impl_.destroy(--impl_.finish_); }

      void erase(iterator pos) noexcept(std::is_nothrow_move_assignable<value_type>::value) {
        std::move(pos + 1, end(), pos);
        pop_back();
      }

      void clear() noexcept {
        while (!empty()) pop_back();
      }

      const_reference operator[](size_type n) const noexcept { return *(impl_.start_ + n); }

      reference operator[](size_type n) noexcept { return *(impl_.start_ + n); }

      iterator begin() noexcept { return iterator(impl_.start_); }

      iterator end() noexcept { return iterator(impl_.finish_); }

      const_iterator cbegin() const noexcept { return const_iterator(impl_.start_); }

      const_iterator begin() const noexcept { return cbegin(); }

      const_iterator cend() const noexcept { return const_iterator(impl_.finish_); }

      const_iterator end() const noexcept { return cend(); }

      pointer data() noexcept { return impl_.start_; }

      const_pointer data() const noexcept { return impl_.start_; }

      std::tuple<pointer, pointer, pointer> release() noexcept {
        auto ret = std::make_tuple(impl_.start_, impl_.finish_, impl_.end_of_storage_);
        impl_.start_ = nullptr;
        impl_.finish_ = nullptr;
        impl_.end_of_storage_ = nullptr;
        return ret;
      }

      allocator_type& get_allocator() noexcept {
        return static_cast<allocator_type&>(impl_.get_allocator());
      }

      allocator_type const& get_allocator() const noexcept {
        return static_cast<allocator_type const&>(impl_.get_allocator());
      }
    };
  }
}
}

#include <archie/utils/test.h>
#include <memory>
namespace cont = archie::utils::containers;

struct resource {
  resource(int i) : handle(new int(i)) {}
  resource(resource const& x) : handle(new int(*(x.handle))) {}
  resource(resource&& x) noexcept : handle(x.handle) { x.handle = nullptr; }
  resource& operator=(resource const& x) {
    if (handle == nullptr)
      handle = new int(*x.handle);
    else
      *handle = *(x.handle);
    return *this;
  }
  resource& operator=(resource&& x) noexcept {
    if (handle) delete handle;
    handle = x.handle;
    x.handle = nullptr;
    return *this;
  }
  ~resource() noexcept {
    if (handle) delete handle;
  }
  int* handle = nullptr;
  friend bool operator==(resource const& r, int i) noexcept { return *r.handle == i; }
  friend bool operator==(int i, resource const& r) noexcept { return r == i; }
  friend bool operator!=(int i, resource const& r) noexcept { return !(r == i); }
  friend bool operator!=(resource const& r, int i) noexcept { return !(r == i); }
};

using darray = cont::dynamic_array<resource>;

void canDefaultConstructDynamicArray() {
  darray da;
  EXPECT_EQ(0u, da.capacity());
  EXPECT_TRUE(da.empty());
}

void canCreateDynamicArrayWithGivenCapacity() {
  darray da1(1);
  darray da3(3);
  EXPECT_EQ(1u, da1.capacity());
  EXPECT_TRUE(da1.empty());

  EXPECT_EQ(3u, da3.capacity());
  EXPECT_TRUE(da3.empty());
}

void canMoveConstructDynamicArray() {
  darray da1(1);
  {
    EXPECT_EQ(1u, da1.capacity());
    EXPECT_TRUE(da1.empty());
  }

  darray da(std::move(da1));
  EXPECT_EQ(0u, da1.capacity());
  EXPECT_TRUE(da1.empty());
  EXPECT_EQ(1u, da.capacity());
  EXPECT_TRUE(da.empty());
}

void canMoveAssign() {
  darray orig(4);
  darray copy(1);
  {
    orig.emplace_back(5);
    orig.emplace_back(7);
    orig.emplace_back(11);
    copy.emplace_back(13);
    EXPECT_EQ(4u, orig.capacity());
    EXPECT_EQ(3u, orig.size());
    EXPECT_EQ(1u, copy.capacity());
    EXPECT_TRUE(copy.full());
  }

  copy = std::move(orig);
  EXPECT_EQ(0u, orig.capacity());
  EXPECT_EQ(4u, copy.capacity());
  EXPECT_EQ(3u, copy.size());
  EXPECT_EQ(5, copy[0]);
  EXPECT_EQ(7, copy[1]);
  EXPECT_EQ(11, copy[2]);
}

void canEmplaceBackElement() {
  darray da(1);
  {
    EXPECT_EQ(1u, da.capacity());
    EXPECT_EQ(0u, da.size());
    EXPECT_TRUE(da.empty());
  }

  da.emplace_back(7);
  EXPECT_EQ(1u, da.capacity());
  EXPECT_EQ(1u, da.size());
  EXPECT_FALSE(da.empty());
  EXPECT_EQ(7, da[0]);
}

void canPopBackElement() {
  darray da(1);
  {
    EXPECT_EQ(1u, da.capacity());
    da.emplace_back(7);
    EXPECT_EQ(1u, da.capacity());
    EXPECT_EQ(1u, da.size());
    EXPECT_FALSE(da.empty());
  }

  da.pop_back();
  EXPECT_EQ(1u, da.capacity());
  EXPECT_EQ(0u, da.size());
  EXPECT_TRUE(da.empty());
}

void canUseBeginAndEnd() {
  darray da0;
  darray da1(1);
  darray da2(2);
  {
    EXPECT_EQ(da0.begin(), da0.end());
    EXPECT_EQ(da1.begin(), da1.end());
    EXPECT_EQ(da2.begin(), da2.end());
  }

  da1.emplace_back(11);
  da2.emplace_back(13);
  {
    EXPECT_EQ(da1.begin() + 1, da1.end());
    EXPECT_EQ(da2.begin() + 1, da2.end());
  }

  da2.emplace_back(17);
  EXPECT_EQ(da2.begin() + 2, da2.end());
}

void canEraseElement() {
  darray da(3);
  {
    da.emplace_back(7);
    da.emplace_back(11);
    da.emplace_back(13);
    EXPECT_EQ(3u, da.size());
    EXPECT_TRUE(da.full());
    EXPECT_EQ(7, da[0]);
    EXPECT_EQ(11, da[1]);
    EXPECT_EQ(13, da[2]);
  }

  da.erase(da.begin());
  {
    EXPECT_EQ(2u, da.size());
    EXPECT_FALSE(da.full());
    EXPECT_EQ(11, da[0]);
    EXPECT_EQ(13, da[1]);
  }

  da.erase(da.begin() + 1);
  {
    EXPECT_EQ(1u, da.size());
    EXPECT_EQ(11, da[0]);
  }

  da.erase(da.begin());
  EXPECT_EQ(3u, da.capacity());
  EXPECT_TRUE(da.empty());
}

void canReleaseContent() {
  darray da(7);
  {
    da.emplace_back(5);
    da.emplace_back(7);
    da.emplace_back(11);
    da.emplace_back(13);
  }

  auto alloc = da.get_allocator();
  darray::pointer first, last, end;
  std::tie(first, last, end) = da.release();
  EXPECT_EQ(4, last - first);
  alloc.deallocate(first, end - first);
}

int main() {
  canDefaultConstructDynamicArray();
  canCreateDynamicArrayWithGivenCapacity();
  canMoveConstructDynamicArray();
  canMoveAssign();
  canEmplaceBackElement();
  canPopBackElement();
  canUseBeginAndEnd();
  canEraseElement();
  canReleaseContent();
  return 0;
}
<commit_msg>copy ctor and copy assign<commit_after>#include <memory>
#include <tuple>
#include <type_traits>

#define IMPLEMENT_ME std::terminate();

namespace archie {
namespace utils {
  namespace containers {
    template <typename Tp, typename Alloc = std::allocator<Tp>>
    struct dynamic_array {
      using allocator_type = Alloc;
      using pointer = typename allocator_type::pointer;
      using const_pointer = typename allocator_type::const_pointer;
      using value_type = typename allocator_type::value_type;
      using reference = typename allocator_type::reference;
      using const_reference = typename allocator_type::const_reference;
      using size_type = typename allocator_type::size_type;
      using difference_type = typename allocator_type::difference_type;

      using iterator = __gnu_cxx::__normal_iterator<pointer, dynamic_array>;
      using const_iterator = __gnu_cxx::__normal_iterator<const_pointer, dynamic_array>;
      using reverse_iterator = std::reverse_iterator<iterator>;
      using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    private:
      using tp_alloc = typename allocator_type::template rebind<Tp>::other;
      struct impl : private tp_alloc {
        using tp_alloc::allocate;
        using tp_alloc::deallocate;
        using tp_alloc::construct;
        using tp_alloc::destroy;

        pointer start_ = nullptr;
        pointer finish_ = nullptr;
        pointer end_of_storage_ = nullptr;

        impl() noexcept = default;

        explicit impl(tp_alloc const& a) noexcept : tp_alloc(a),
                                                    start_(nullptr),
                                                    finish_(nullptr),
                                                    end_of_storage_(nullptr) {}

        void create_storage(size_type n) {
          if (n != size_type(end_of_storage_ - start_)) {
            start_ = (n != 0u) ? allocate(n) : nullptr;
            finish_ = start_;
            end_of_storage_ = start_ + n;
          }
        }

        void destroy_storage() noexcept {
          deallocate(start_, end_of_storage_ - start_);
          start_ = nullptr;
          finish_ = nullptr;
          end_of_storage_ = nullptr;
        }

        tp_alloc& get_allocator() noexcept { return static_cast<tp_alloc&>(*this); }

        tp_alloc const& get_allocator() const noexcept {
          return static_cast<tp_alloc const&>(*this);
        }

        void swap(impl& x) noexcept {
          std::swap(start_, x.start_);
          std::swap(finish_, x.finish_);
          std::swap(end_of_storage_, x.end_of_storage_);
          std::swap(get_allocator(), x.get_allocator());
        }
      };

      impl impl_;

    public:
      dynamic_array() = default;

      explicit dynamic_array(size_type n) { impl_.create_storage(n); }

      dynamic_array(size_type n, allocator_type const& a) : impl_(a) { impl_.create_storage(n); }

      dynamic_array(dynamic_array&& x) noexcept { impl_.swap(x.impl_); }

      dynamic_array& operator=(dynamic_array&& x) noexcept {
        clear();
        if (capacity() != 0u) impl_.destroy_storage();
        impl_.swap(x.impl_);
        return *this;
      }

      dynamic_array(dynamic_array const& x) : dynamic_array(x.capacity()) {
        std::copy(std::begin(x), std::end(x), std::back_inserter(*this));
      }

      dynamic_array& operator=(dynamic_array const& x) {
        clear();
        if (capacity() != x.capacity() && capacity() != 0u) {
          impl_.destroy_storage();
          impl_.create_storage(x.capacity());
        }
        std::copy(std::begin(x), std::end(x), std::back_inserter(*this));
        return *this;
      }

      dynamic_array(std::initializer_list<value_type>) { IMPLEMENT_ME }

      dynamic_array& operator=(std::initializer_list<value_type>) {
        IMPLEMENT_ME
        return *this;
      }

      template <typename InputIterator>
      dynamic_array(InputIterator, InputIterator) {
        IMPLEMENT_ME
      }

      ~dynamic_array() noexcept {
        clear();
        if (capacity() != 0u) impl_.destroy_storage();
      }

      size_type capacity() const noexcept {
        return size_type(impl_.end_of_storage_ - impl_.start_);
      }

      size_type size() const noexcept { return size_type(impl_.finish_ - impl_.start_); }

      bool empty() const noexcept { return cbegin() == cend(); }

      bool full() const noexcept { return impl_.finish_ == impl_.end_of_storage_; }

      template <typename... Args>
      void emplace_back(Args&&... args) noexcept(
          std::is_nothrow_constructible<value_type, Args...>::value) {
        impl_.construct(impl_.finish_, std::forward<Args>(args)...);
        ++impl_.finish_;
      }

      void push_back(const_reference x) noexcept(
          std::is_nothrow_copy_constructible<value_type>::value) {
        emplace_back(x);
      }

      void push_back(value_type&& x) noexcept(
          std::is_nothrow_move_constructible<value_type>::value) {
        emplace_back(std::move(x));
      }

      void pop_back() noexcept { impl_.destroy(--impl_.finish_); }

      void erase(iterator pos) noexcept(std::is_nothrow_move_assignable<value_type>::value) {
        std::move(pos + 1, end(), pos);
        pop_back();
      }

      void clear() noexcept {
        while (!empty()) pop_back();
      }

      const_reference operator[](size_type n) const noexcept { return *(impl_.start_ + n); }

      reference operator[](size_type n) noexcept { return *(impl_.start_ + n); }

      iterator begin() noexcept { return iterator(impl_.start_); }

      iterator end() noexcept { return iterator(impl_.finish_); }

      const_iterator cbegin() const noexcept { return const_iterator(impl_.start_); }

      const_iterator begin() const noexcept { return cbegin(); }

      const_iterator cend() const noexcept { return const_iterator(impl_.finish_); }

      const_iterator end() const noexcept { return cend(); }

      pointer data() noexcept { return impl_.start_; }

      const_pointer data() const noexcept { return impl_.start_; }

      std::tuple<pointer, pointer, pointer> release() noexcept {
        auto ret = std::make_tuple(impl_.start_, impl_.finish_, impl_.end_of_storage_);
        impl_.start_ = nullptr;
        impl_.finish_ = nullptr;
        impl_.end_of_storage_ = nullptr;
        return ret;
      }

      allocator_type& get_allocator() noexcept {
        return static_cast<allocator_type&>(impl_.get_allocator());
      }

      allocator_type const& get_allocator() const noexcept {
        return static_cast<allocator_type const&>(impl_.get_allocator());
      }
    };
  }
}
}

#include <archie/utils/test.h>
#include <memory>
namespace cont = archie::utils::containers;

struct resource {
  resource(int i) : handle(new int(i)) {}
  resource(resource const& x) : handle(new int(*(x.handle))) {}
  resource(resource&& x) noexcept : handle(x.handle) { x.handle = nullptr; }
  resource& operator=(resource const& x) {
    if (handle == nullptr)
      handle = new int(*x.handle);
    else
      *handle = *(x.handle);
    return *this;
  }
  resource& operator=(resource&& x) noexcept {
    if (handle) delete handle;
    handle = x.handle;
    x.handle = nullptr;
    return *this;
  }
  ~resource() noexcept {
    if (handle) delete handle;
  }
  int* handle = nullptr;
  friend bool operator==(resource const& lhs, resource const& rhs) noexcept {
    return *lhs.handle == *rhs.handle;
  }
  friend bool operator==(resource const& r, int i) noexcept { return *r.handle == i; }
  friend bool operator==(int i, resource const& r) noexcept { return r == i; }
  friend bool operator!=(int i, resource const& r) noexcept { return !(r == i); }
  friend bool operator!=(resource const& r, int i) noexcept { return !(r == i); }
};

using darray = cont::dynamic_array<resource>;

void canDefaultConstructDynamicArray() {
  darray da;
  EXPECT_EQ(0u, da.capacity());
  EXPECT_TRUE(da.empty());
}

void canCreateDynamicArrayWithGivenCapacity() {
  darray da1(1);
  darray da3(3);
  EXPECT_EQ(1u, da1.capacity());
  EXPECT_TRUE(da1.empty());

  EXPECT_EQ(3u, da3.capacity());
  EXPECT_TRUE(da3.empty());
}

void canMoveConstructDynamicArray() {
  darray da1(1);
  {
    EXPECT_EQ(1u, da1.capacity());
    EXPECT_TRUE(da1.empty());
  }

  darray da(std::move(da1));
  EXPECT_EQ(0u, da1.capacity());
  EXPECT_TRUE(da1.empty());
  EXPECT_EQ(1u, da.capacity());
  EXPECT_TRUE(da.empty());
}

void canMoveAssign() {
  darray orig(4);
  darray copy(1);
  {
    orig.emplace_back(5);
    orig.emplace_back(7);
    orig.emplace_back(11);
    copy.emplace_back(13);
    EXPECT_EQ(4u, orig.capacity());
    EXPECT_EQ(3u, orig.size());
    EXPECT_EQ(1u, copy.capacity());
    EXPECT_TRUE(copy.full());
  }

  copy = std::move(orig);
  EXPECT_EQ(0u, orig.capacity());
  EXPECT_EQ(4u, copy.capacity());
  EXPECT_EQ(3u, copy.size());
  EXPECT_EQ(5, copy[0]);
  EXPECT_EQ(7, copy[1]);
  EXPECT_EQ(11, copy[2]);
}

void canCopyConstruct() {
  darray orig(4);
  {
    orig.emplace_back(5);
    orig.emplace_back(7);
    orig.emplace_back(11);
  }

  darray copy(orig);
  {
    EXPECT_EQ(orig.capacity(), copy.capacity());
    EXPECT_EQ(orig.size(), copy.size());
    EXPECT_NE(orig.data(), copy.data());
    EXPECT_EQ(orig[0], copy[0]);
    EXPECT_EQ(orig[1], copy[1]);
    EXPECT_EQ(orig[2], copy[2]);
  }
}

void canCopyAssign() {
  darray orig(4);
  darray copy(1);
  {
    orig.emplace_back(5);
    orig.emplace_back(7);
    orig.emplace_back(11);
    copy.emplace_back(13);
  }

  copy = orig;
  {
    EXPECT_EQ(orig.capacity(), copy.capacity());
    EXPECT_EQ(orig.size(), copy.size());
    EXPECT_NE(orig.data(), copy.data());
    EXPECT_EQ(orig[0], copy[0]);
    EXPECT_EQ(orig[1], copy[1]);
    EXPECT_EQ(orig[2], copy[2]);
  }
}

void canEmplaceBackElement() {
  darray da(1);
  {
    EXPECT_EQ(1u, da.capacity());
    EXPECT_EQ(0u, da.size());
    EXPECT_TRUE(da.empty());
  }

  da.emplace_back(7);
  EXPECT_EQ(1u, da.capacity());
  EXPECT_EQ(1u, da.size());
  EXPECT_FALSE(da.empty());
  EXPECT_EQ(7, da[0]);
}

void canPopBackElement() {
  darray da(1);
  {
    EXPECT_EQ(1u, da.capacity());
    da.emplace_back(7);
    EXPECT_EQ(1u, da.capacity());
    EXPECT_EQ(1u, da.size());
    EXPECT_FALSE(da.empty());
  }

  da.pop_back();
  EXPECT_EQ(1u, da.capacity());
  EXPECT_EQ(0u, da.size());
  EXPECT_TRUE(da.empty());
}

void canUseBeginAndEnd() {
  darray da0;
  darray da1(1);
  darray da2(2);
  {
    EXPECT_EQ(da0.begin(), da0.end());
    EXPECT_EQ(da1.begin(), da1.end());
    EXPECT_EQ(da2.begin(), da2.end());
  }

  da1.emplace_back(11);
  da2.emplace_back(13);
  {
    EXPECT_EQ(da1.begin() + 1, da1.end());
    EXPECT_EQ(da2.begin() + 1, da2.end());
  }

  da2.emplace_back(17);
  EXPECT_EQ(da2.begin() + 2, da2.end());
}

void canEraseElement() {
  darray da(3);
  {
    da.emplace_back(7);
    da.emplace_back(11);
    da.emplace_back(13);
    EXPECT_EQ(3u, da.size());
    EXPECT_TRUE(da.full());
    EXPECT_EQ(7, da[0]);
    EXPECT_EQ(11, da[1]);
    EXPECT_EQ(13, da[2]);
  }

  da.erase(da.begin());
  {
    EXPECT_EQ(2u, da.size());
    EXPECT_FALSE(da.full());
    EXPECT_EQ(11, da[0]);
    EXPECT_EQ(13, da[1]);
  }

  da.erase(da.begin() + 1);
  {
    EXPECT_EQ(1u, da.size());
    EXPECT_EQ(11, da[0]);
  }

  da.erase(da.begin());
  EXPECT_EQ(3u, da.capacity());
  EXPECT_TRUE(da.empty());
}

void canReleaseContent() {
  darray da(7);
  {
    da.emplace_back(5);
    da.emplace_back(7);
    da.emplace_back(11);
    da.emplace_back(13);
  }

  auto alloc = da.get_allocator();
  darray::pointer first, last, end;
  std::tie(first, last, end) = da.release();
  EXPECT_EQ(4, last - first);
  alloc.deallocate(first, end - first);
}

int main() {
  canDefaultConstructDynamicArray();
  canCreateDynamicArrayWithGivenCapacity();
  canMoveConstructDynamicArray();
  canMoveAssign();
  canCopyConstruct();
  canCopyAssign();
  canEmplaceBackElement();
  canPopBackElement();
  canUseBeginAndEnd();
  canEraseElement();
  canReleaseContent();
  return 0;
}
<|endoftext|>


<commit_before>#include <shogun/base/init.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/kernel/LinearKernel.h>
#include <shogun/labels/BinaryLabels.h>
#include <shogun/classifier/svm/LibSVM.h>
#include <iostream>
using namespace shogun;
void print_message(FILE* target, const char* str)
{
	fprintf(target, "%s", str);
}
//generates data points (of different classes) randomly
void gen_rand_data(SGMatrix<float64_t> features, SGVector<float64_t> labels, float64_t distance)
{
	index_t num_samples=labels.vlen;
	index_t dimensions=features.num_rows;
	for (int32_t i=0; i<num_samples; i++)
	{
		if (i<num_samples/2)
		{
			labels[i]=-1.0;
			for(int32_t j=0; j<dimensions; j++)
				features(j,i)=CMath::random(0.0,1.0)+distance;
		}
		else
		{
			labels[i]=1.0;
			for(int32_t j=0; j<dimensions; j++)
				features(j,i)=CMath::random(0.0,1.0)-distance;
		}
	}
	labels.display_vector("labels");
	features.display_matrix("features");
}
int main(int argc, char** argv)
{
	init_shogun(&print_message, &print_message, &print_message);

	const int32_t feature_cache=0;
	const float64_t svm_C=10;
	const float64_t svm_eps=0.001;

	index_t num_samples=20;
	index_t dimensions=2;
	float64_t dist=0.5;

	SGMatrix<float64_t> featureMatrix(dimensions,num_samples);
	SGVector<float64_t> labelVector(num_samples);
	//random generation of data
	gen_rand_data(featureMatrix,labelVector,dist);

	//create train labels
	CLabels* labels=new CBinaryLabels(labelVector);

	//create train features
	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(0);
	SG_REF(features);
	features->set_feature_matrix(featureMatrix);

	//create linear kernel
	CLinearKernel* kernel=new CLinearKernel();
	SG_REF(kernel);
	kernel->init(features, features);

	//create svm classifier by LibSVM
	CLibSVM* svm=new CLibSVM(svm_C,kernel, labels);
	SG_REF(svm);
	svm->set_epsilon(svm_eps);
	svm->train();

	//classify data points
	CBinaryLabels* out_labels=CBinaryLabels::obtain_from_generic(svm->apply());

	//convert scores to calibrated probabilities  by fitting a sigmoid function
    //using the method described in Lin, H., Lin, C., and Weng,  R. (2007). A note
	//on Platt's probabilistic outputs for support vector machines.
	out_labels->scores_to_probabilities();

	//display output labels and probabilities
	for (int32_t i=0; i<num_samples; i++)
	{
		SG_SPRINT("out[%d]=%f (%f)\n", i, out_labels->get_label(i),
				out_labels->get_value(i));
	}

	//clean up
	SG_UNREF(out_labels);
	SG_UNREF(kernel);
	SG_UNREF(features);
	SG_UNREF(svm);

	exit_shogun();

	return 0;
}
<commit_msg>file removed<commit_after><|endoftext|>


<commit_before>#pragma once
#define UNROLL_LOOP 0
#define DUMMY_PAR_2 3
#define DUMMY_PAR_3 a
<commit_msg>more small fixes<commit_after>#pragma once
#define UNROLL_LOOP 0
#define DUMMY_PAR_2 2
#define DUMMY_PAR_3 a
<|endoftext|>


<commit_before>//
// Copyright (c) 2018-2020, University of Edinburgh, University of Oxford
// 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  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.
//

#include <exotica_core_task_maps/joint_pose.h>

REGISTER_TASKMAP_TYPE("JointPose", exotica::JointPose);

namespace exotica
{
void JointPose::Update(Eigen::VectorXdRefConst q, Eigen::VectorXdRef phi)
{
    if (phi.rows() != static_cast<int>(joint_map_.size())) ThrowNamed("Wrong size of Phi!");
    for (std::size_t i = 0; i < joint_map_.size(); ++i)
    {
        phi(i) = q(joint_map_[i]) - joint_ref_(i);
    }
}

void JointPose::Update(Eigen::VectorXdRefConst q, Eigen::VectorXdRef phi, Eigen::MatrixXdRef jacobian)
{
    if (phi.rows() != static_cast<int>(joint_map_.size())) ThrowNamed("Wrong size of Phi!");
    if (jacobian.rows() != static_cast<int>(joint_map_.size()) || jacobian.cols() != num_controlled_joints_) ThrowNamed("Wrong size of jacobian! " << num_controlled_joints_);
    for (std::size_t i = 0; i < joint_map_.size(); ++i)
    {
        phi(i) = q(joint_map_[i]) - joint_ref_(i);
        jacobian(i, joint_map_[i]) = 1.0;
    }
}

void JointPose::Update(Eigen::VectorXdRefConst q, Eigen::VectorXdRef phi, Eigen::MatrixXdRef jacobian, HessianRef hessian)
{
    // Hessian is 0
    Update(q, phi, jacobian);
}

void JointPose::AssignScene(ScenePtr scene)
{
    scene_ = scene;
    Initialize();
}

void JointPose::Initialize()
{
    num_controlled_joints_ = scene_->GetKinematicTree().GetNumControlledJoints();
    if (parameters_.JointMap.rows() > 0)
    {
        joint_map_.resize(parameters_.JointMap.rows());
        for (int i = 0; i < parameters_.JointMap.rows(); ++i)
        {
            joint_map_[i] = parameters_.JointMap(i);
        }
    }
    else
    {
        joint_map_.resize(num_controlled_joints_);
        for (int i = 0; i < num_controlled_joints_; ++i)
        {
            joint_map_[i] = i;
        }
    }

    if (parameters_.JointRef.rows() > 0)
    {
        joint_ref_ = parameters_.JointRef;
        if (joint_ref_.rows() != static_cast<int>(joint_map_.size())) ThrowNamed("Invalid joint reference size! Expecting " << joint_map_.size() << " but received " << joint_ref_.rows());
    }
    else
    {
        joint_ref_ = Eigen::VectorXd::Zero(joint_map_.size());
    }
}

int JointPose::TaskSpaceDim()
{
    return joint_map_.size();
}
}  // namespace exotica
<commit_msg>[exotica_core_task_maps] JointPose: Implement get_joint_ref, get_joint_map<commit_after>//
// Copyright (c) 2018-2020, University of Edinburgh, University of Oxford
// 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  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.
//

#include <exotica_core_task_maps/joint_pose.h>

REGISTER_TASKMAP_TYPE("JointPose", exotica::JointPose);

namespace exotica
{
void JointPose::Update(Eigen::VectorXdRefConst q, Eigen::VectorXdRef phi)
{
    if (phi.rows() != static_cast<int>(joint_map_.size())) ThrowNamed("Wrong size of Phi!");
    for (std::size_t i = 0; i < joint_map_.size(); ++i)
    {
        phi(i) = q(joint_map_[i]) - joint_ref_(i);
    }
}

void JointPose::Update(Eigen::VectorXdRefConst q, Eigen::VectorXdRef phi, Eigen::MatrixXdRef jacobian)
{
    if (phi.rows() != static_cast<int>(joint_map_.size())) ThrowNamed("Wrong size of Phi!");
    if (jacobian.rows() != static_cast<int>(joint_map_.size()) || jacobian.cols() != num_controlled_joints_) ThrowNamed("Wrong size of jacobian! " << num_controlled_joints_);
    for (std::size_t i = 0; i < joint_map_.size(); ++i)
    {
        phi(i) = q(joint_map_[i]) - joint_ref_(i);
        jacobian(i, joint_map_[i]) = 1.0;
    }
}

void JointPose::Update(Eigen::VectorXdRefConst q, Eigen::VectorXdRef phi, Eigen::MatrixXdRef jacobian, HessianRef hessian)
{
    // Hessian is 0
    Update(q, phi, jacobian);
}

void JointPose::AssignScene(ScenePtr scene)
{
    scene_ = scene;
    Initialize();
}

void JointPose::Initialize()
{
    num_controlled_joints_ = scene_->GetKinematicTree().GetNumControlledJoints();
    if (parameters_.JointMap.rows() > 0)
    {
        joint_map_.resize(parameters_.JointMap.rows());
        for (int i = 0; i < parameters_.JointMap.rows(); ++i)
        {
            joint_map_[i] = parameters_.JointMap(i);
        }
    }
    else
    {
        joint_map_.resize(num_controlled_joints_);
        for (int i = 0; i < num_controlled_joints_; ++i)
        {
            joint_map_[i] = i;
        }
    }

    if (parameters_.JointRef.rows() > 0)
    {
        joint_ref_ = parameters_.JointRef;
        if (joint_ref_.rows() != static_cast<int>(joint_map_.size())) ThrowNamed("Invalid joint reference size! Expecting " << joint_map_.size() << " but received " << joint_ref_.rows());
    }
    else
    {
        joint_ref_ = Eigen::VectorXd::Zero(joint_map_.size());
    }
}

int JointPose::TaskSpaceDim()
{
    return joint_map_.size();
}

const std::vector<int>& JointPose::get_joint_map() const
{
    return joint_map_;
}

const Eigen::VectorXd& JointPose::get_joint_ref() const
{
    return joint_ref_;
}

}  // namespace exotica
<|endoftext|>