<commit_before>/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_plot_spectrocurve.h"
#include "qwt_color_map.h"
#include "qwt_scale_map.h"
#include "qwt_painter.h"
#include <qpainter.h>

class QwtPlotSpectroCurve::PrivateData
{
public:
    PrivateData():
        colorRange( 0.0, 1000.0 ),
        penWidth(0.0),
        paintAttributes( QwtPlotSpectroCurve::ClipPoints )
    {
        colorMap = new QwtLinearColorMap();
    }

    ~PrivateData()
    {
        delete colorMap;
    }

    QwtColorMap *colorMap;
    QwtInterval colorRange;
    QVector<QRgb> colorTable;
    double penWidth;
    QwtPlotSpectroCurve::PaintAttributes paintAttributes;
};

/*!
  Constructor
  \param title Title of the curve
*/
QwtPlotSpectroCurve::QwtPlotSpectroCurve( const QwtText &title ):
    QwtPlotSeriesItem( title )
{
    init();
}

/*!
  Constructor
  \param title Title of the curve
*/
QwtPlotSpectroCurve::QwtPlotSpectroCurve( const QString &title ):
    QwtPlotSeriesItem( QwtText( title ) )
{
    init();
}

//! Destructor
QwtPlotSpectroCurve::~QwtPlotSpectroCurve()
{
    delete d_data;
}

/*!
  \brief Initialize data members
*/
void QwtPlotSpectroCurve::init()
{
    setItemAttribute( QwtPlotItem::Legend );
    setItemAttribute( QwtPlotItem::AutoScale );

    d_data = new PrivateData;
    setData( new QwtPoint3DSeriesData() );

    setZ( 20.0 );
}

//! \return QwtPlotItem::Rtti_PlotSpectroCurve
int QwtPlotSpectroCurve::rtti() const
{
    return QwtPlotItem::Rtti_PlotSpectroCurve;
}

/*!
  Specify an attribute how to draw the curve

  \param attribute Paint attribute
  \param on On/Off
  /sa PaintAttribute, testPaintAttribute()
*/
void QwtPlotSpectroCurve::setPaintAttribute( PaintAttribute attribute, bool on )
{
    if ( on )
        d_data->paintAttributes |= attribute;
    else
        d_data->paintAttributes &= ~attribute;
}

/*!
    \brief Return the current paint attributes
    \sa PaintAttribute, setPaintAttribute()
*/
bool QwtPlotSpectroCurve::testPaintAttribute( PaintAttribute attribute ) const
{
    return ( d_data->paintAttributes & attribute );
}

/*!
  Initialize data with an array of samples.
  \param samples Vector of points
*/
void QwtPlotSpectroCurve::setSamples( const QVector<QwtPoint3D> &samples )
{
    setData( new QwtPoint3DSeriesData( samples ) );
}

/*!
  Change the color map

  Often it is useful to display the mapping between intensities and
  colors as an additional plot axis, showing a color bar.

  \param colorMap Color Map

  \sa colorMap(), setColorRange(), QwtColorMap::color(),
      QwtScaleWidget::setColorBarEnabled(), QwtScaleWidget::setColorMap()
*/
void QwtPlotSpectroCurve::setColorMap( QwtColorMap *colorMap )
{
    if ( colorMap != d_data->colorMap )
    {
        delete d_data->colorMap;
        d_data->colorMap = colorMap;
    }

    legendChanged();
    itemChanged();
}

/*!
   \return Color Map used for mapping the intensity values to colors
   \sa setColorMap(), setColorRange(), QwtColorMap::color()
*/
const QwtColorMap *QwtPlotSpectroCurve::colorMap() const
{
    return d_data->colorMap;
}

/*!
   Set the value interval, that corresponds to the color map

   \param interval interval.minValue() corresponds to 0.0,
                   interval.maxValue() to 1.0 on the color map.

   \sa colorRange(), setColorMap(), QwtColorMap::color()
*/
void QwtPlotSpectroCurve::setColorRange( const QwtInterval &interval )
{
    if ( interval != d_data->colorRange )
    {
        d_data->colorRange = interval;

        legendChanged();
        itemChanged();
    }
}

/*!
  \return Value interval, that corresponds to the color map
  \sa setColorRange(), setColorMap(), QwtColorMap::color()
*/
QwtInterval &QwtPlotSpectroCurve::colorRange() const
{
    return d_data->colorRange;
}

/*!
  Assign a pen width

  \param penWidth New pen width
  \sa penWidth()
*/
void QwtPlotSpectroCurve::setPenWidth(double penWidth)
{
    if ( penWidth < 0.0 )
        penWidth = 0.0;

    if ( d_data->penWidth != penWidth )
    {
        d_data->penWidth = penWidth;

        legendChanged();
        itemChanged();
    }
}

/*!
  \return Pen width used to draw a dot
  \sa setPenWidth()
*/
double QwtPlotSpectroCurve::penWidth() const
{
    return d_data->penWidth;
}

/*!
  Draw a subset of the points

  \param painter Painter
  \param xMap Maps x-values into pixel coordinates.
  \param yMap Maps y-values into pixel coordinates.
  \param canvasRect Contents rect of the canvas
  \param from Index of the first sample to be painted
  \param to Index of the last sample to be painted. If to < 0 the
         series will be painted to its last sample.

  \sa drawDots()
*/
void QwtPlotSpectroCurve::drawSeries( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect, int from, int to ) const
{
    if ( !painter || dataSize() <= 0 )
        return;

    if ( to < 0 )
        to = dataSize() - 1;

    if ( from < 0 )
        from = 0;

    if ( from >= to )
        return;

    drawDots( painter, xMap, yMap, canvasRect, from, to );
}

/*!
  Draw a subset of the points

  \param painter Painter
  \param xMap Maps x-values into pixel coordinates.
  \param yMap Maps y-values into pixel coordinates.
  \param canvasRect Contents rect of the canvas
  \param from Index of the first sample to be painted
  \param to Index of the last sample to be painted. If to < 0 the
         series will be painted to its last sample.

  \sa drawSeries()
*/
void QwtPlotSpectroCurve::drawDots( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect, int from, int to ) const
{
    if ( !d_data->colorRange.isValid() )
        return;

    const bool doAlign = QwtPainter::roundingAlignment( painter );

    const QwtColorMap::Format format = d_data->colorMap->format();
    if ( format == QwtColorMap::Indexed )
        d_data->colorTable = d_data->colorMap->colorTable( d_data->colorRange );

    const QwtSeriesData<QwtPoint3D> *series = data();

    for ( int i = from; i <= to; i++ )
    {
        const QwtPoint3D sample = series->sample( i );

        double xi = xMap.transform( sample.x() );
        double yi = yMap.transform( sample.y() );
        if ( doAlign )
        {
            xi = qRound( xi );
            yi = qRound( yi );
        }

        if ( d_data->paintAttributes & QwtPlotSpectroCurve::ClipPoints )
        {
            if ( !canvasRect.contains( xi, yi ) )
                continue;
        }

        if ( format == QwtColorMap::RGB )
        {
            const QRgb rgb = d_data->colorMap->rgb(
                d_data->colorRange, sample.z() );

            painter->setPen( QPen( QColor( rgb ), d_data->penWidth ) );
        }
        else
        {
            const unsigned char index = d_data->colorMap->colorIndex(
                d_data->colorRange, sample.z() );

            painter->setPen( QPen( QColor( d_data->colorTable[index] ),
                d_data->penWidth ) );
        }

        QwtPainter::drawPoint( painter, QPointF( xi, yi ) );
    }

    d_data->colorTable.clear();
}
<commit_msg>fix for curves with one point<commit_after>/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_plot_spectrocurve.h"
#include "qwt_color_map.h"
#include "qwt_scale_map.h"
#include "qwt_painter.h"
#include <qpainter.h>

class QwtPlotSpectroCurve::PrivateData
{
public:
    PrivateData():
        colorRange( 0.0, 1000.0 ),
        penWidth(0.0),
        paintAttributes( QwtPlotSpectroCurve::ClipPoints )
    {
        colorMap = new QwtLinearColorMap();
    }

    ~PrivateData()
    {
        delete colorMap;
    }

    QwtColorMap *colorMap;
    QwtInterval colorRange;
    QVector<QRgb> colorTable;
    double penWidth;
    QwtPlotSpectroCurve::PaintAttributes paintAttributes;
};

/*!
  Constructor
  \param title Title of the curve
*/
QwtPlotSpectroCurve::QwtPlotSpectroCurve( const QwtText &title ):
    QwtPlotSeriesItem( title )
{
    init();
}

/*!
  Constructor
  \param title Title of the curve
*/
QwtPlotSpectroCurve::QwtPlotSpectroCurve( const QString &title ):
    QwtPlotSeriesItem( QwtText( title ) )
{
    init();
}

//! Destructor
QwtPlotSpectroCurve::~QwtPlotSpectroCurve()
{
    delete d_data;
}

/*!
  \brief Initialize data members
*/
void QwtPlotSpectroCurve::init()
{
    setItemAttribute( QwtPlotItem::Legend );
    setItemAttribute( QwtPlotItem::AutoScale );

    d_data = new PrivateData;
    setData( new QwtPoint3DSeriesData() );

    setZ( 20.0 );
}

//! \return QwtPlotItem::Rtti_PlotSpectroCurve
int QwtPlotSpectroCurve::rtti() const
{
    return QwtPlotItem::Rtti_PlotSpectroCurve;
}

/*!
  Specify an attribute how to draw the curve

  \param attribute Paint attribute
  \param on On/Off
  /sa PaintAttribute, testPaintAttribute()
*/
void QwtPlotSpectroCurve::setPaintAttribute( PaintAttribute attribute, bool on )
{
    if ( on )
        d_data->paintAttributes |= attribute;
    else
        d_data->paintAttributes &= ~attribute;
}

/*!
    \brief Return the current paint attributes
    \sa PaintAttribute, setPaintAttribute()
*/
bool QwtPlotSpectroCurve::testPaintAttribute( PaintAttribute attribute ) const
{
    return ( d_data->paintAttributes & attribute );
}

/*!
  Initialize data with an array of samples.
  \param samples Vector of points
*/
void QwtPlotSpectroCurve::setSamples( const QVector<QwtPoint3D> &samples )
{
    setData( new QwtPoint3DSeriesData( samples ) );
}

/*!
  Change the color map

  Often it is useful to display the mapping between intensities and
  colors as an additional plot axis, showing a color bar.

  \param colorMap Color Map

  \sa colorMap(), setColorRange(), QwtColorMap::color(),
      QwtScaleWidget::setColorBarEnabled(), QwtScaleWidget::setColorMap()
*/
void QwtPlotSpectroCurve::setColorMap( QwtColorMap *colorMap )
{
    if ( colorMap != d_data->colorMap )
    {
        delete d_data->colorMap;
        d_data->colorMap = colorMap;
    }

    legendChanged();
    itemChanged();
}

/*!
   \return Color Map used for mapping the intensity values to colors
   \sa setColorMap(), setColorRange(), QwtColorMap::color()
*/
const QwtColorMap *QwtPlotSpectroCurve::colorMap() const
{
    return d_data->colorMap;
}

/*!
   Set the value interval, that corresponds to the color map

   \param interval interval.minValue() corresponds to 0.0,
                   interval.maxValue() to 1.0 on the color map.

   \sa colorRange(), setColorMap(), QwtColorMap::color()
*/
void QwtPlotSpectroCurve::setColorRange( const QwtInterval &interval )
{
    if ( interval != d_data->colorRange )
    {
        d_data->colorRange = interval;

        legendChanged();
        itemChanged();
    }
}

/*!
  \return Value interval, that corresponds to the color map
  \sa setColorRange(), setColorMap(), QwtColorMap::color()
*/
QwtInterval &QwtPlotSpectroCurve::colorRange() const
{
    return d_data->colorRange;
}

/*!
  Assign a pen width

  \param penWidth New pen width
  \sa penWidth()
*/
void QwtPlotSpectroCurve::setPenWidth(double penWidth)
{
    if ( penWidth < 0.0 )
        penWidth = 0.0;

    if ( d_data->penWidth != penWidth )
    {
        d_data->penWidth = penWidth;

        legendChanged();
        itemChanged();
    }
}

/*!
  \return Pen width used to draw a dot
  \sa setPenWidth()
*/
double QwtPlotSpectroCurve::penWidth() const
{
    return d_data->penWidth;
}

/*!
  Draw a subset of the points

  \param painter Painter
  \param xMap Maps x-values into pixel coordinates.
  \param yMap Maps y-values into pixel coordinates.
  \param canvasRect Contents rect of the canvas
  \param from Index of the first sample to be painted
  \param to Index of the last sample to be painted. If to < 0 the
         series will be painted to its last sample.

  \sa drawDots()
*/
void QwtPlotSpectroCurve::drawSeries( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect, int from, int to ) const
{
    if ( !painter || dataSize() <= 0 )
        return;

    if ( to < 0 )
        to = dataSize() - 1;

    if ( from < 0 )
        from = 0;

    if ( from > to )
        return;

    drawDots( painter, xMap, yMap, canvasRect, from, to );
}

/*!
  Draw a subset of the points

  \param painter Painter
  \param xMap Maps x-values into pixel coordinates.
  \param yMap Maps y-values into pixel coordinates.
  \param canvasRect Contents rect of the canvas
  \param from Index of the first sample to be painted
  \param to Index of the last sample to be painted. If to < 0 the
         series will be painted to its last sample.

  \sa drawSeries()
*/
void QwtPlotSpectroCurve::drawDots( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect, int from, int to ) const
{
    if ( !d_data->colorRange.isValid() )
        return;

    const bool doAlign = QwtPainter::roundingAlignment( painter );

    const QwtColorMap::Format format = d_data->colorMap->format();
    if ( format == QwtColorMap::Indexed )
        d_data->colorTable = d_data->colorMap->colorTable( d_data->colorRange );

    const QwtSeriesData<QwtPoint3D> *series = data();

    for ( int i = from; i <= to; i++ )
    {
        const QwtPoint3D sample = series->sample( i );

        double xi = xMap.transform( sample.x() );
        double yi = yMap.transform( sample.y() );
        if ( doAlign )
        {
            xi = qRound( xi );
            yi = qRound( yi );
        }

        if ( d_data->paintAttributes & QwtPlotSpectroCurve::ClipPoints )
        {
            if ( !canvasRect.contains( xi, yi ) )
                continue;
        }

        if ( format == QwtColorMap::RGB )
        {
            const QRgb rgb = d_data->colorMap->rgb(
                d_data->colorRange, sample.z() );

            painter->setPen( QPen( QColor( rgb ), d_data->penWidth ) );
        }
        else
        {
            const unsigned char index = d_data->colorMap->colorIndex(
                d_data->colorRange, sample.z() );

            painter->setPen( QPen( QColor( d_data->colorTable[index] ),
                d_data->penWidth ) );
        }

        QwtPainter::drawPoint( painter, QPointF( xi, yi ) );
    }

    d_data->colorTable.clear();
}
<|endoftext|>


<commit_before>#include "ride/runner.h"
#include <wx/utils.h>
#include <wx/process.h>
#include <wx/txtstrm.h>

#include "ride/mainwindow.h"

class PipedProcess;
class Process;

const int RUNNER_CONSOLE_OPTION = wxEXEC_HIDE_CONSOLE;
// const int RUNNER_CONSOLE_OPTION = wxEXEC_SHOW_CONSOLE;

//////////////////////////////////////////////////////////////////////////

Command::Command(const wxString& r, const wxString& c) : root(r), cmd(c) {
}

//////////////////////////////////////////////////////////////////////////

// idle timer to keep the process updated since wx apperently doesn't do that
class IdleTimer : public wxTimer {
public:
  IdleTimer(SingleRunner::Pimpl* p) : pimpl_(p) {
  }
  void Notify();

  SingleRunner::Pimpl* pimpl_;
};

//////////////////////////////////////////////////////////////////////////

struct SingleRunner::Pimpl {
  explicit Pimpl(SingleRunner* p) : parent_(p), processes_(NULL), delete_processes_(NULL), pid_(0), exit_code_(-1) {
    assert(parent_);
    idle_timer_.reset(new IdleTimer(this));
  }
  ~Pimpl();

  void Append(const wxString& s) {
    parent_->Append(s);
  }

  void MarkForDeletion(Process *process);

  bool RunCmd(const Command& cmd);

  void Notify();

  void OnCompleted() {
    assert(parent_);
    parent_->Completed();
    idle_timer_->Stop();
  }

  SingleRunner* parent_;
  Process* processes_; // the current running process or NULL
  Process* delete_processes_; // process to be deleted at the end
  long pid_; // the id of the current or previous running process
  int exit_code_;
  std::unique_ptr<IdleTimer> idle_timer_;
};

void IdleTimer::Notify() {
  pimpl_->Notify();
}

class Process : public wxProcess
{
public:
  Process(SingleRunner::Pimpl* project, const wxString& cmd)
    : wxProcess(wxPROCESS_DEFAULT), cmd_(cmd)
  {
    runner_ = project;
    Redirect();
  }

  virtual void OnTerminate(int pid, int status) {
    assert(runner_->pid_ == pid);

    // show the rest of the output
    while (HasInput()) {}
    runner_->MarkForDeletion(this);

    runner_->Append(wxString::Format(wxT("Process %u ('%s') terminated with exit code %d."),
      pid, cmd_.c_str(), status));
    runner_->Append("");
    runner_->exit_code_ = status;
    runner_->OnCompleted();
  }

  virtual bool HasInput() {
    // original source: http://sourceforge.net/p/fourpane/code/HEAD/tree/trunk/ExecuteInDialog.cpp

    // The original used wxTextInputStream to read a line at a time.  Fine, except when there was no \n, whereupon the thing would hang
    // Instead, read the stream (which may occasionally contain non-ascii bytes e.g. from g++) into a memorybuffer, then to a wxString

    bool hasInput = false;

    while (IsInputAvailable()) {
      wxMemoryBuffer buf;
      do {
        const char c = GetInputStream()->GetC();

        if (GetInputStream()->Eof()) break;
        if (c == wxT('\n')) break;
        buf.AppendByte(c);
      } while (IsInputAvailable());

      wxString line((const char*)buf.GetData(), wxConvUTF8, buf.GetDataLen()); // Convert the line to utf8
      runner_->Append(line);
      hasInput = true;
    }

    while (IsErrorAvailable())
    {
      wxMemoryBuffer buf;
      do
      {
        const char c = GetErrorStream()->GetC();

        if (GetErrorStream()->Eof()) break;
        if (c == wxT('\n')) break;
        buf.AppendByte(c);
      } while (IsErrorAvailable());

      wxString line((const char*)buf.GetData(), wxConvUTF8, buf.GetDataLen());
      runner_->Append(line);
      hasInput = true;
    }

    return hasInput;
  }

protected:
  SingleRunner::Pimpl *runner_;
  wxString cmd_;
};

void SingleRunner::Pimpl::Notify(){
  if (processes_) {
    // sometimes the output hangs until we close the window
    // seems to be waiting for output or something
    // getting the input in a callback seems to remove the waiting...
    processes_->HasInput();
  }
}

bool SingleRunner::Pimpl::RunCmd(const Command& c) {
  Process* process = new Process(this, c.cmd);
  Append("> " + c.cmd);

  wxExecuteEnv env;
  env.cwd = c.root;

  const int flags = wxEXEC_ASYNC | RUNNER_CONSOLE_OPTION;

  const long process_id = wxExecute(c.cmd, flags, process, &env);

  // async call
  if (!process_id) {
    Append(wxT("Execution failed."));
    delete process;
    return false;
  }

  assert(processes_ == NULL);
  assert(pid_ == 0);
  processes_ = process;
  pid_ = process_id;

  idle_timer_->Start(100);
  return true;
}

void SingleRunner::Pimpl::MarkForDeletion(Process *process)
{
  assert(processes_ == process);
  processes_ = NULL;
  delete_processes_ = process;
}

SingleRunner::Pimpl:: ~Pimpl() {
  delete delete_processes_;
}

//////////////////////////////////////////////////////////////////////////

SingleRunner::SingleRunner() : pimpl(new Pimpl(this)) {
}

SingleRunner::~SingleRunner() {
}

bool SingleRunner::RunCmd(const Command& cmd) {
  assert(pimpl);
  assert(this->IsRunning() == false);
  return pimpl->RunCmd(cmd);
}

bool SingleRunner::IsRunning() const {
  return pimpl->processes_ != NULL;
}

void SingleRunner::Completed() {
  // empty
}

int SingleRunner::GetExitCode() {
  assert(this->IsRunning() == false);
  assert(pimpl->pid_ != 0);
  return pimpl->exit_code_;
}

//////////////////////////////////////////////////////////////////////////

class MultiRunner::Runner : public SingleRunner {
public:
  Runner(MultiRunner* r) : runner_(r) {
    assert(runner_);
  }

  virtual void Append(const wxString& str) {
    assert(runner_);
    runner_->Append(str);
  }
  virtual void Completed() {
    assert(runner_);
    runner_->RunNext(GetExitCode());
  }
  bool Run(const Command& cmd) {
    return RunCmd(cmd);
  }
private:
  MultiRunner* runner_;
};

MultiRunner::MultiRunner(){
}

MultiRunner::~MultiRunner(){
}

bool MultiRunner::RunCmd(const Command& cmd) {
  commands_.push_back(cmd);
  if (IsRunning() == true) return true;
  return RunNext(0);
}

bool MultiRunner::RunNext(int last_exit_code) {
  assert(IsRunning() == false);
  if (commands_.empty()) return false;

  if (last_exit_code == 0) {
    last_runner_ = runner_;
    runner_.reset(new Runner(this));
    const bool run_result = runner_->Run(*commands_.begin());
    if (run_result) {
      commands_.erase(commands_.begin());
    }
    return run_result;
  }
  else {
    commands_.clear();
    return false;
  }
}

bool MultiRunner::IsRunning() const {
  if (runner_) {
    return runner_->IsRunning();
  }
  return false;
}
<commit_msg>fixed bugs with cmdrunner endless loop<commit_after>#include "ride/runner.h"
#include <wx/utils.h>
#include <wx/process.h>
#include <wx/txtstrm.h>

#include "ride/mainwindow.h"

class PipedProcess;
class Process;

const int RUNNER_CONSOLE_OPTION = wxEXEC_HIDE_CONSOLE;
// const int RUNNER_CONSOLE_OPTION = wxEXEC_SHOW_CONSOLE;

//////////////////////////////////////////////////////////////////////////

Command::Command(const wxString& r, const wxString& c) : root(r), cmd(c) {
}

//////////////////////////////////////////////////////////////////////////

// idle timer to keep the process updated since wx apperently doesn't do that
class IdleTimer : public wxTimer {
public:
  IdleTimer(SingleRunner::Pimpl* p) : pimpl_(p) {
  }
  void Notify();

  SingleRunner::Pimpl* pimpl_;
};

//////////////////////////////////////////////////////////////////////////

struct SingleRunner::Pimpl {
  explicit Pimpl(SingleRunner* p) : parent_(p), processes_(NULL), delete_processes_(NULL), pid_(0), exit_code_(-1) {
    assert(parent_);
    idle_timer_.reset(new IdleTimer(this));
  }
  ~Pimpl();

  void Append(const wxString& s) {
    parent_->Append(s);
  }

  void MarkForDeletion(Process *process);

  bool RunCmd(const Command& cmd);

  void Notify();

  void OnCompleted() {
    assert(parent_);
    parent_->Completed();
    idle_timer_->Stop();
  }

  SingleRunner* parent_;
  Process* processes_; // the current running process or NULL
  Process* delete_processes_; // process to be deleted at the end
  long pid_; // the id of the current or previous running process
  int exit_code_;
  std::unique_ptr<IdleTimer> idle_timer_;
};

void IdleTimer::Notify() {
  pimpl_->Notify();
}

class Process : public wxProcess
{
public:
  Process(SingleRunner::Pimpl* project, const wxString& cmd)
    : wxProcess(wxPROCESS_DEFAULT), cmd_(cmd), null_members_called_(false)
  {
    runner_ = project;
    Redirect();
  }

  virtual void OnTerminate(int pid, int status) {
    if (runner_) {
      assert(runner_->pid_ == pid);

      // show the rest of the output
      while (HasInput()) {}
      runner_->MarkForDeletion(this);

      runner_->Append(wxString::Format(wxT("Process %u ('%s') terminated with exit code %d."),
        pid, cmd_.c_str(), status));
      runner_->Append("");
      runner_->exit_code_ = status;
      runner_->OnCompleted();
    }
    else {
      // if we are here that should mean we have called have called NullMember()
      // That should mean that we are done with the object and we
      // can delete this here, *fingers crossed*
      assert(null_members_called_);
      delete this;
    }
  }

  virtual bool HasInput() {
    // original source: http://sourceforge.net/p/fourpane/code/HEAD/tree/trunk/ExecuteInDialog.cpp

    // The original used wxTextInputStream to read a line at a time.  Fine, except when there was no \n, whereupon the thing would hang
    // Instead, read the stream (which may occasionally contain non-ascii bytes e.g. from g++) into a memorybuffer, then to a wxString

    bool hasInput = false;

    while (IsInputAvailable()) {
      wxMemoryBuffer buf;
      do {
        const char c = GetInputStream()->GetC();

        if (GetInputStream()->Eof()) break;
        if (c == wxT('\n')) break;
        buf.AppendByte(c);
      } while (IsInputAvailable());

      wxString line((const char*)buf.GetData(), wxConvUTF8, buf.GetDataLen()); // Convert the line to utf8
      runner_->Append(line);
      hasInput = true;
    }

    while (IsErrorAvailable())
    {
      wxMemoryBuffer buf;
      do
      {
        const char c = GetErrorStream()->GetC();

        if (GetErrorStream()->Eof()) break;
        if (c == wxT('\n')) break;
        buf.AppendByte(c);
      } while (IsErrorAvailable());

      wxString line((const char*)buf.GetData(), wxConvUTF8, buf.GetDataLen());
      runner_->Append(line);
      hasInput = true;
    }

    return hasInput;
  }

  void NullMembers() {
    runner_ = NULL;
    null_members_called_ = true;
  }

protected:
  SingleRunner::Pimpl *runner_;
  wxString cmd_;
  bool null_members_called_;
};

void SingleRunner::Pimpl::Notify(){
  if (processes_) {
    // sometimes the output hangs until we close the window
    // seems to be waiting for output or something
    // getting the input in a callback seems to remove the waiting...
    processes_->HasInput();
  }
}

bool SingleRunner::Pimpl::RunCmd(const Command& c) {
  Process* process = new Process(this, c.cmd);
  Append("> " + c.cmd);

  wxExecuteEnv env;
  env.cwd = c.root;

  const int flags = wxEXEC_ASYNC | RUNNER_CONSOLE_OPTION;

  const long process_id = wxExecute(c.cmd, flags, process, &env);

  // async call
  if (!process_id) {
    Append(wxT("Execution failed."));
    delete process;
    return false;
  }

  assert(processes_ == NULL);
  assert(pid_ == 0);
  processes_ = process;
  pid_ = process_id;

  idle_timer_->Start(100);
  return true;
}

void SingleRunner::Pimpl::MarkForDeletion(Process *process)
{
  assert(processes_ == process);
  processes_ = NULL;
  delete_processes_ = process;
}

SingleRunner::Pimpl:: ~Pimpl() {
  if (processes_ ) processes_->NullMembers();
  if (delete_processes_) delete_processes_->NullMembers();
  delete delete_processes_;
}

//////////////////////////////////////////////////////////////////////////

SingleRunner::SingleRunner() : pimpl(new Pimpl(this)) {
}

SingleRunner::~SingleRunner() {
}

bool SingleRunner::RunCmd(const Command& cmd) {
  assert(pimpl);
  assert(this->IsRunning() == false);
  return pimpl->RunCmd(cmd);
}

bool SingleRunner::IsRunning() const {
  const bool has_process = pimpl->processes_ != NULL;
  if (has_process) {
    const bool exists = wxProcess::Exists(pimpl->processes_->GetPid());
    pimpl->processes_->HasInput();
    if (exists == false) return false;
  }
  return has_process;
}

void SingleRunner::Completed() {
  // empty
}

int SingleRunner::GetExitCode() {
  assert(this->IsRunning() == false);
  assert(pimpl->pid_ != 0);
  return pimpl->exit_code_;
}

//////////////////////////////////////////////////////////////////////////

class MultiRunner::Runner : public SingleRunner {
public:
  Runner(MultiRunner* r) : runner_(r) {
    assert(runner_);
  }

  virtual void Append(const wxString& str) {
    assert(runner_);
    runner_->Append(str);
  }
  virtual void Completed() {
    assert(runner_);
    runner_->RunNext(GetExitCode());
  }
  bool Run(const Command& cmd) {
    return RunCmd(cmd);
  }
private:
  MultiRunner* runner_;
};

MultiRunner::MultiRunner(){
}

MultiRunner::~MultiRunner(){
}

bool MultiRunner::RunCmd(const Command& cmd) {
  commands_.push_back(cmd);
  if (IsRunning() == true) return true;
  return RunNext(0);
}

bool MultiRunner::RunNext(int last_exit_code) {
  assert(IsRunning() == false);
  if (commands_.empty()) return false;

  if (last_exit_code == 0) {
    last_runner_ = runner_;
    runner_.reset(new Runner(this));
    const bool run_result = runner_->Run(*commands_.begin());
    if (run_result) {
      commands_.erase(commands_.begin());
    }
    return run_result;
  }
  else {
    commands_.clear();
    return false;
  }
}

bool MultiRunner::IsRunning() const {
  if (runner_) {
    return runner_->IsRunning();
  }
  return false;
}
<|endoftext|>


<commit_before>#include "TextureAtlas.hpp"
#include "vec.hpp"

using namespace rffalcon;

TextureAtlas::TextureAtlas(const int width, const int height, const int depth)
	: _width(width), _height(height), _depth(depth)
{
	// starter node for fitting algorithm
	// contains padding in atlas to avoid sampling artifacts
	rffalcon::ivec3 paddingNode = { { 1, 1, width - 2 } };
	_nodes.push_back(paddingNode);
	_data = new unsigned char[width * height * depth]();
}

TextureAtlas::~TextureAtlas()
{
	delete [] _data;
	_data = nullptr;
}

int TextureAtlas::getWidth() const
{
	return _width;
}

int TextureAtlas::getHeight() const
{
	return _height;
}

int TextureAtlas::getDepth() const
{
	return _depth;
}

GLuint TextureAtlas::getGLTextureId() const
{
	return _glTextureId;
}

rffalcon::ivec4 TextureAtlas::getRegion(const int width, const int height)
{
	int bestY = INT_MAX;
	int bestWidth = INT_MAX;
	int bestIndex = -1;
	size_t nodeCount = _nodes.size();
	rffalcon::ivec4 region = { { -1, -1, width, height } };

	for (size_t index = 0; index < nodeCount; ++index)
	{
		int y = _fit(index, width, height);
		if (y >= 0) {
			rffalcon::ivec3 node = _nodes[index];
			if (y < bestY || (y == bestY && node.width < bestWidth))
			{
				bestY = y;
				bestIndex = index;
				bestWidth = node.width;
				region.x = node.x;
				region.y = node.yNext;
			}
		}
	}

	if (bestIndex != -1)
	{
		_addNode(region, bestIndex);
		_reduceNodes(bestIndex);
		_mergeNodes();
	}

	return region;
}

// Add node to envelope
void TextureAtlas::_addNode(rffalcon::ivec4 region, int index)
{
	rffalcon::ivec3 node;
	node.x = region.x;
	node.yNext = region.y + region.height;
	node.width = region.width;
	_nodes.insert(_nodes.begin() + index, node);
}

// Remove nodes that are no longer part of the envelope
void TextureAtlas::_reduceNodes(int startIndex)
{
	for (size_t index = startIndex + 1; index < _nodes.size(); ++index)
	{
		rffalcon::ivec3 curNode = _nodes[index];
		rffalcon::ivec3 prevNode = _nodes[index - 1];
		if (curNode.x < (prevNode.x + prevNode.width))
		{
			_nodes.erase(_nodes.begin() + index);
			int widthReduction = prevNode.x + prevNode.width - curNode.x;
			curNode.width -= widthReduction;
			if (curNode.width <= 0)
			{
				--index;
			}
			else
			{
				curNode.x += widthReduction;
				_nodes.insert(_nodes.begin() + index, curNode);
				// reduced width of the curNode, rest of envelope will be unaffected
				break;
			}
		}
		else
		{
			// rest of envelope unaffected
			break;
		}
	}
}

// Merge adjacent nodes on the envelope that have the same yNext value
void TextureAtlas::_mergeNodes()
{
	for (size_t index = 0; index < _nodes.size() - 1; ++index)
	{
		rffalcon::ivec3 curNode = _nodes[index];
		rffalcon::ivec3 nextNode = _nodes[index + 1];
		if (curNode.yNext == nextNode.yNext)
		{
			curNode.width += nextNode.width;
			_nodes.erase(_nodes.begin() + index + 1);
			--index;
		}
	}
}

int TextureAtlas::_fit(const int index, const int width, const int height)
{
	rffalcon::ivec3 node = _nodes[index];
	int x = node.x;
	int y = node.y;
	int widthLeft = width;
	int curIndex = index;
	int result = -1;

	// if adding this node left-aligned to the node at the index
	// would not go outside right edge of the texture
	if ((x + width) <= (_width - 1))
	{
		// move the new node's y position to the envelope
		y = node.yNext;
		// while this node might collide with the envelope in the x direction
		while (widthLeft > 0)
		{
			node = _nodes[curIndex];
			// if the new node collides with the envelope in the x direction
			if (node.yNext > y)
			{
				// push the new node down to the envelope
				y = node.yNext;
			}

			// if adding this node would not go outside the bottom edge of the texture
			if ((y + height) <= (_height - 1))
			{
				widthLeft -= node.width;
				++curIndex;
			}
			else
			{
				// No room to add the new node below the index node
				y = -1;
				break;
			}
		}
		result = y;
	}

	return result;
}

void TextureAtlas::setRegion(rffalcon::ivec4 region, GlyphData glyphData)
{
	int depth = getDepth();
	int charSize = sizeof(char);
	for (int i = 0; i < glyphData.height; ++i)
	{
		memcpy(_data + ((region.y + i) * getWidth() + region.x) * charSize * depth,
			   glyphData.buffer + (i * glyphData.pitch * charSize), glyphData.width * charSize * depth);
	}

}

void TextureAtlas::upload()
{
	if (_glTextureId == 0)
	{
		glGenTextures(1, &_glTextureId);
	}

	glBindTexture(GL_TEXTURE_2D, _glTextureId);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	GLenum pixelDataType;
	GLint internalFormat;
	GLenum format;
	if (_depth == 4)
	{
#ifdef GL_UNSIGNED_INT_8_8_8_8_REV
		pixelDataType = GL_UNSIGNED_INT_8_8_8_8_REV;
		format = GL_BGRA;
#else
		pixelDataType = GL_UNSIGNED_BYTE;
		format = GL_RGBA;
#endif
		internalFormat = GL_RGBA;
	}
	else {
		pixelDataType = GL_UNSIGNED_BYTE;
		format = internalFormat = (_depth == 3) ? GL_RGB : GL_RED;
	}

	glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, _width, _height, 0, format, pixelDataType, _data);
}<commit_msg>Update TextureAtlas.cpp<commit_after>#include <cstring>
#include "TextureAtlas.hpp"
#include "vec.hpp"

using namespace rffalcon;

TextureAtlas::TextureAtlas(const int width, const int height, const int depth)
	: _width(width), _height(height), _depth(depth)
{
	// starter node for fitting algorithm
	// contains padding in atlas to avoid sampling artifacts
	rffalcon::ivec3 paddingNode = { { 1, 1, width - 2 } };
	_nodes.push_back(paddingNode);
	_data = new unsigned char[width * height * depth]();
}

TextureAtlas::~TextureAtlas()
{
	delete [] _data;
	_data = nullptr;
}

int TextureAtlas::getWidth() const
{
	return _width;
}

int TextureAtlas::getHeight() const
{
	return _height;
}

int TextureAtlas::getDepth() const
{
	return _depth;
}

GLuint TextureAtlas::getGLTextureId() const
{
	return _glTextureId;
}

rffalcon::ivec4 TextureAtlas::getRegion(const int width, const int height)
{
	int bestY = INT_MAX;
	int bestWidth = INT_MAX;
	int bestIndex = -1;
	size_t nodeCount = _nodes.size();
	rffalcon::ivec4 region = { { -1, -1, width, height } };

	for (size_t index = 0; index < nodeCount; ++index)
	{
		int y = _fit(index, width, height);
		if (y >= 0) {
			rffalcon::ivec3 node = _nodes[index];
			if (y < bestY || (y == bestY && node.width < bestWidth))
			{
				bestY = y;
				bestIndex = index;
				bestWidth = node.width;
				region.x = node.x;
				region.y = node.yNext;
			}
		}
	}

	if (bestIndex != -1)
	{
		_addNode(region, bestIndex);
		_reduceNodes(bestIndex);
		_mergeNodes();
	}

	return region;
}

// Add node to envelope
void TextureAtlas::_addNode(rffalcon::ivec4 region, int index)
{
	rffalcon::ivec3 node;
	node.x = region.x;
	node.yNext = region.y + region.height;
	node.width = region.width;
	_nodes.insert(_nodes.begin() + index, node);
}

// Remove nodes that are no longer part of the envelope
void TextureAtlas::_reduceNodes(int startIndex)
{
	for (size_t index = startIndex + 1; index < _nodes.size(); ++index)
	{
		rffalcon::ivec3 curNode = _nodes[index];
		rffalcon::ivec3 prevNode = _nodes[index - 1];
		if (curNode.x < (prevNode.x + prevNode.width))
		{
			_nodes.erase(_nodes.begin() + index);
			int widthReduction = prevNode.x + prevNode.width - curNode.x;
			curNode.width -= widthReduction;
			if (curNode.width <= 0)
			{
				--index;
			}
			else
			{
				curNode.x += widthReduction;
				_nodes.insert(_nodes.begin() + index, curNode);
				// reduced width of the curNode, rest of envelope will be unaffected
				break;
			}
		}
		else
		{
			// rest of envelope unaffected
			break;
		}
	}
}

// Merge adjacent nodes on the envelope that have the same yNext value
void TextureAtlas::_mergeNodes()
{
	for (size_t index = 0; index < _nodes.size() - 1; ++index)
	{
		rffalcon::ivec3 curNode = _nodes[index];
		rffalcon::ivec3 nextNode = _nodes[index + 1];
		if (curNode.yNext == nextNode.yNext)
		{
			curNode.width += nextNode.width;
			_nodes.erase(_nodes.begin() + index + 1);
			--index;
		}
	}
}

int TextureAtlas::_fit(const int index, const int width, const int height)
{
	rffalcon::ivec3 node = _nodes[index];
	int x = node.x;
	int y = node.y;
	int widthLeft = width;
	int curIndex = index;
	int result = -1;

	// if adding this node left-aligned to the node at the index
	// would not go outside right edge of the texture
	if ((x + width) <= (_width - 1))
	{
		// move the new node's y position to the envelope
		y = node.yNext;
		// while this node might collide with the envelope in the x direction
		while (widthLeft > 0)
		{
			node = _nodes[curIndex];
			// if the new node collides with the envelope in the x direction
			if (node.yNext > y)
			{
				// push the new node down to the envelope
				y = node.yNext;
			}

			// if adding this node would not go outside the bottom edge of the texture
			if ((y + height) <= (_height - 1))
			{
				widthLeft -= node.width;
				++curIndex;
			}
			else
			{
				// No room to add the new node below the index node
				y = -1;
				break;
			}
		}
		result = y;
	}

	return result;
}

void TextureAtlas::setRegion(rffalcon::ivec4 region, GlyphData glyphData)
{
	int depth = getDepth();
	int charSize = sizeof(char);
	for (int i = 0; i < glyphData.height; ++i)
	{
		std::memcpy(_data + ((region.y + i) * getWidth() + region.x) * charSize * depth,
			   glyphData.buffer + (i * glyphData.pitch * charSize), glyphData.width * charSize * depth);
	}

}

void TextureAtlas::upload()
{
	if (_glTextureId == 0)
	{
		glGenTextures(1, &_glTextureId);
	}

	glBindTexture(GL_TEXTURE_2D, _glTextureId);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	GLenum pixelDataType;
	GLint internalFormat;
	GLenum format;
	if (_depth == 4)
	{
#ifdef GL_UNSIGNED_INT_8_8_8_8_REV
		pixelDataType = GL_UNSIGNED_INT_8_8_8_8_REV;
		format = GL_BGRA;
#else
		pixelDataType = GL_UNSIGNED_BYTE;
		format = GL_RGBA;
#endif
		internalFormat = GL_RGBA;
	}
	else {
		pixelDataType = GL_UNSIGNED_BYTE;
		format = internalFormat = (_depth == 3) ? GL_RGB : GL_RED;
	}

	glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, _width, _height, 0, format, pixelDataType, _data);
}
<|endoftext|>


<commit_before>#include "platform.hpp"

#include "../base/logging.hpp"

#include "../coding/file_reader.hpp"

#include "../std/target_os.hpp"
#include "../std/algorithm.hpp"

#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QTemporaryFile>

////////////////////////////////////////////////////////////////////////////////////////
ModelReader * Platform::GetReader(string const & file) const
{
  return new FileReader(ReadPathForFile(file), 10, 12);
}

bool Platform::GetFileSizeByFullPath(string const & filePath, uint64_t & size)
{
  QFileInfo f(filePath.c_str());
  size = static_cast<uint64_t>(f.size());
  return size != 0;
}

bool Platform::GetFileSizeByName(string const & fileName, uint64_t & size) const
{
  try
  {
    return GetFileSizeByFullPath(ReadPathForFile(fileName), size);
  }
  catch (std::exception const &)
  {
    return false;
  }
}

void Platform::GetFilesInDir(string const & directory, string const & mask, FilesList & outFiles)
{
  QDir dir(directory.c_str(), mask.c_str(), QDir::Unsorted,
           QDir::Files | QDir::Readable | QDir::Dirs | QDir::NoDotAndDotDot);
  int const count = dir.count();
  for (int i = 0; i < count; ++i)
    outFiles.push_back(dir[i].toUtf8().data());
}

string Platform::DeviceName() const
{
  return OMIM_OS_NAME;
}

double Platform::VisualScale() const
{
  return 1.0;
}

string Platform::SkinName() const
{
  return "basic_ldpi.skn";
}

void Platform::GetFontNames(FilesList & res) const
{
  GetFilesInDir(ResourcesDir(), "*.ttf", res);
  GetFilesInDir(WritableDir(), "*.ttf", res);
  sort(res.begin(), res.end());
  res.erase(unique(res.begin(), res.end()), res.end());
  CHECK(!res.empty(), ("Can't find any valid font in", ResourcesDir(), WritableDir()));
}

int Platform::MaxTilesCount() const
{
  return 30;
}

int Platform::TileSize() const
{
  return 512;
}

int Platform::ScaleEtalonSize() const
{
  return 512 + 256;
}

int Platform::VideoMemoryLimit() const
{
  return 20 * 1024 * 1024;
}

bool Platform::IsFeatureSupported(string const & feature) const
{
  if (feature == "search")
    return true;
  return false;
}

///////////////////////////////////////////////////////////////////////////////
extern "C" Platform & GetPlatform()
{
  static Platform platform;
  return platform;
}
<commit_msg>changed default skin name for desktop systems.<commit_after>#include "platform.hpp"

#include "../base/logging.hpp"

#include "../coding/file_reader.hpp"

#include "../std/target_os.hpp"
#include "../std/algorithm.hpp"

#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QTemporaryFile>

////////////////////////////////////////////////////////////////////////////////////////
ModelReader * Platform::GetReader(string const & file) const
{
  return new FileReader(ReadPathForFile(file), 10, 12);
}

bool Platform::GetFileSizeByFullPath(string const & filePath, uint64_t & size)
{
  QFileInfo f(filePath.c_str());
  size = static_cast<uint64_t>(f.size());
  return size != 0;
}

bool Platform::GetFileSizeByName(string const & fileName, uint64_t & size) const
{
  try
  {
    return GetFileSizeByFullPath(ReadPathForFile(fileName), size);
  }
  catch (std::exception const &)
  {
    return false;
  }
}

void Platform::GetFilesInDir(string const & directory, string const & mask, FilesList & outFiles)
{
  QDir dir(directory.c_str(), mask.c_str(), QDir::Unsorted,
           QDir::Files | QDir::Readable | QDir::Dirs | QDir::NoDotAndDotDot);
  int const count = dir.count();
  for (int i = 0; i < count; ++i)
    outFiles.push_back(dir[i].toUtf8().data());
}

string Platform::DeviceName() const
{
  return OMIM_OS_NAME;
}

double Platform::VisualScale() const
{
  return 1.0;
}

string Platform::SkinName() const
{
  return "basic_mdpi.skn";
}

void Platform::GetFontNames(FilesList & res) const
{
  GetFilesInDir(ResourcesDir(), "*.ttf", res);
  GetFilesInDir(WritableDir(), "*.ttf", res);
  sort(res.begin(), res.end());
  res.erase(unique(res.begin(), res.end()), res.end());
  CHECK(!res.empty(), ("Can't find any valid font in", ResourcesDir(), WritableDir()));
}

int Platform::MaxTilesCount() const
{
  return 30;
}

int Platform::TileSize() const
{
  return 512;
}

int Platform::ScaleEtalonSize() const
{
  return 512 + 256;
}

int Platform::VideoMemoryLimit() const
{
  return 20 * 1024 * 1024;
}

bool Platform::IsFeatureSupported(string const & feature) const
{
  if (feature == "search")
    return true;
  return false;
}

///////////////////////////////////////////////////////////////////////////////
extern "C" Platform & GetPlatform()
{
  static Platform platform;
  return platform;
}
<|endoftext|>


<commit_before>/*
 * qucrc_t.cpp
 *
 *
 * version 1.0
 *
 *
 * Copyright (c) 2015, Koynov Stas - skojnov@yandex.ru
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1 Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  2 Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  3 Neither the name of the <organization> nor the
 *    names of its contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY 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 <COPYRIGHT HOLDER> 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 "qucrc_t.h"

const std::vector<CRC_Param_Info> QuCRC_t::CRC_List = QuCRC_t::get_crc_list();

CRC_Param_Info::CRC_Param_Info(QString _name, uint8_t _bits, uint64_t _poly, uint64_t _init, bool _ref_in, bool _ref_out, uint64_t _xor_out) :
    name(_name),
    bits(_bits),
    poly(_poly),
    init(_init),
    ref_in(_ref_in),
    ref_out(_ref_out),
    xor_out(_xor_out)
{
}

QuCRC_t::QuCRC_t(QObject *parent) :
    QObject(parent)
{
    index = find_index();
}

int QuCRC_t::set_bits(uint8_t new_bits)
{
    if( new_bits == ucrc.get_bits() )
        return 0;

    int ret = ucrc.set_bits(new_bits);
    if( ret == 0 )
    {
        update_index();
        emit param_changed();
    }

    return ret;
}

void QuCRC_t::set_poly(uint64_t new_poly)
{
    if( new_poly == ucrc.get_poly() )
        return;

    ucrc.set_poly(new_poly);

    update_index();
    emit param_changed();
}

void QuCRC_t::set_init(uint64_t new_init)
{
    if( new_init == ucrc.get_init() )
        return;

    ucrc.set_init(new_init);

    update_index();
    emit param_changed();
}

void QuCRC_t::set_xor_out(uint64_t new_xor_out)
{
    if( new_xor_out == ucrc.get_xor_out() )
        return;

    ucrc.set_xor_out(new_xor_out);

    update_index();
    emit param_changed();
}

void QuCRC_t::set_ref_in(bool new_ref_in)
{
    if( new_ref_in == ucrc.get_ref_in() )
        return;

    ucrc.set_ref_in(new_ref_in);

    update_index();
    emit param_changed();
}

void QuCRC_t::set_ref_out(bool new_ref_out)
{
    if( new_ref_out == ucrc.get_ref_out() )
        return;

    ucrc.set_ref_out(new_ref_out);

    update_index();
    emit param_changed();
}

int QuCRC_t::set_index(uint32_t new_index)
{
    if( new_index == index)
        return 0; //good job

    if( new_index >= CRC_List.size() )
        return -1; // new_index is bad

    index = new_index;

    //set crc param for new_index
    CRC_Param_Info tmp = CRC_List[new_index];

    ucrc.set_bits(tmp.bits);
    ucrc.set_poly(tmp.poly);
    ucrc.set_init(tmp.init);
    ucrc.set_xor_out(tmp.xor_out);
    ucrc.set_ref_in(tmp.ref_in);
    ucrc.set_ref_out(tmp.ref_out);

    emit index_changed(index);
    emit param_changed();

    return 0; //good job
}

uint32_t QuCRC_t::find_index()
{

    for(size_t i = 0; i < CRC_List.size(); ++i)
    {
        CRC_Param_Info tmp = CRC_List[i];

        if(
            tmp.bits    == ucrc.get_bits()    &&
            tmp.poly    == ucrc.get_poly()    &&
            tmp.init    == ucrc.get_init()    &&
            tmp.xor_out == ucrc.get_xor_out() &&
            tmp.ref_in  == ucrc.get_ref_in()  &&
            tmp.ref_out == ucrc.get_ref_out()
          )
            return i; //found
    }

    return 0; //not found
}

void QuCRC_t::update_index()
{
    uint32_t new_index = find_index();

    if( index == new_index )
        return;

    index = new_index;
    emit index_changed(index);
}

const std::vector<CRC_Param_Info> QuCRC_t::get_crc_list()
{
    std::vector<CRC_Param_Info> crc_list;

    crc_list.push_back(CRC_Param_Info("Custom", 0, 0, 0, false, false, 0) );

    crc_list.push_back(CRC_Param_Info("CRC-32", 32, 0x04c11db7, 0xffffffff, true, true, 0xffffffff) );

    return crc_list;
}
<commit_msg>Update CRC_List<commit_after>/*
 * qucrc_t.cpp
 *
 *
 * version 1.0
 *
 *
 * Copyright (c) 2015, Koynov Stas - skojnov@yandex.ru
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1 Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  2 Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  3 Neither the name of the <organization> nor the
 *    names of its contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY 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 <COPYRIGHT HOLDER> 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 "qucrc_t.h"

const std::vector<CRC_Param_Info> QuCRC_t::CRC_List = QuCRC_t::get_crc_list();

CRC_Param_Info::CRC_Param_Info(QString _name, uint8_t _bits, uint64_t _poly, uint64_t _init, bool _ref_in, bool _ref_out, uint64_t _xor_out) :
    name(_name),
    bits(_bits),
    poly(_poly),
    init(_init),
    ref_in(_ref_in),
    ref_out(_ref_out),
    xor_out(_xor_out)
{
}

QuCRC_t::QuCRC_t(QObject *parent) :
    QObject(parent)
{
    index = find_index();
}

int QuCRC_t::set_bits(uint8_t new_bits)
{
    if( new_bits == ucrc.get_bits() )
        return 0;

    int ret = ucrc.set_bits(new_bits);
    if( ret == 0 )
    {
        update_index();
        emit param_changed();
    }

    return ret;
}

void QuCRC_t::set_poly(uint64_t new_poly)
{
    if( new_poly == ucrc.get_poly() )
        return;

    ucrc.set_poly(new_poly);

    update_index();
    emit param_changed();
}

void QuCRC_t::set_init(uint64_t new_init)
{
    if( new_init == ucrc.get_init() )
        return;

    ucrc.set_init(new_init);

    update_index();
    emit param_changed();
}

void QuCRC_t::set_xor_out(uint64_t new_xor_out)
{
    if( new_xor_out == ucrc.get_xor_out() )
        return;

    ucrc.set_xor_out(new_xor_out);

    update_index();
    emit param_changed();
}

void QuCRC_t::set_ref_in(bool new_ref_in)
{
    if( new_ref_in == ucrc.get_ref_in() )
        return;

    ucrc.set_ref_in(new_ref_in);

    update_index();
    emit param_changed();
}

void QuCRC_t::set_ref_out(bool new_ref_out)
{
    if( new_ref_out == ucrc.get_ref_out() )
        return;

    ucrc.set_ref_out(new_ref_out);

    update_index();
    emit param_changed();
}

int QuCRC_t::set_index(uint32_t new_index)
{
    if( new_index == index)
        return 0; //good job

    if( new_index >= CRC_List.size() )
        return -1; // new_index is bad

    index = new_index;

    //set crc param for new_index
    CRC_Param_Info tmp = CRC_List[new_index];

    ucrc.set_bits(tmp.bits);
    ucrc.set_poly(tmp.poly);
    ucrc.set_init(tmp.init);
    ucrc.set_xor_out(tmp.xor_out);
    ucrc.set_ref_in(tmp.ref_in);
    ucrc.set_ref_out(tmp.ref_out);

    emit index_changed(index);
    emit param_changed();

    return 0; //good job
}

uint32_t QuCRC_t::find_index()
{

    for(size_t i = 0; i < CRC_List.size(); ++i)
    {
        CRC_Param_Info tmp = CRC_List[i];

        if(
            tmp.bits    == ucrc.get_bits()    &&
            tmp.poly    == ucrc.get_poly()    &&
            tmp.init    == ucrc.get_init()    &&
            tmp.xor_out == ucrc.get_xor_out() &&
            tmp.ref_in  == ucrc.get_ref_in()  &&
            tmp.ref_out == ucrc.get_ref_out()
          )
            return i; //found
    }

    return 0; //not found
}

void QuCRC_t::update_index()
{
    uint32_t new_index = find_index();

    if( index == new_index )
        return;

    index = new_index;
    emit index_changed(index);
}

const std::vector<CRC_Param_Info> QuCRC_t::get_crc_list()
{
    std::vector<CRC_Param_Info> crc_list;

    crc_list.push_back(CRC_Param_Info("Custom", 0, 0, 0, false, false, 0) );

    // CRC-3
    crc_list.push_back(CRC_Param_Info("CRC-3/ROHC", 3, 0x3, 0x7, true, true, 0x0) );

    // CRC-4
    crc_list.push_back(CRC_Param_Info("CRC-4/ITU", 4, 0x3, 0x0, true, true, 0x0) );

    // CRC-5
    crc_list.push_back(CRC_Param_Info("CRC-5/EPC", 5, 0x09, 0x09, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-5/ITU", 5, 0x15, 0x00, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-5/USB", 5, 0x05, 0x1f, true,  true,  0x1f) );

    // CRC-6
    crc_list.push_back(CRC_Param_Info("CRC-6/CDMA2000-A", 6, 0x27, 0x3f, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-6/CDMA2000-B", 6, 0x07, 0x3f, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-6/DARC",       6, 0x19, 0x00, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-6/ITU",        6, 0x03, 0x00, true,  true,  0x0) );

    // CRC-7
    crc_list.push_back(CRC_Param_Info("CRC-7",      7, 0x09, 0x0,  false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-7/ROHC", 7, 0x4f, 0x7f, true,  true,  0x0) );

    // CRC-8
    crc_list.push_back(CRC_Param_Info("CRC-8",          8, 0x07, 0x00, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-8/CDMA2000", 8, 0x9b, 0xff, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-8/DARC",     8, 0x39, 0x00, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-8/DVB-S2",   8, 0xd5, 0x00, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-8/EBU",      8, 0x1d, 0xff, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-8/I-CODE",   8, 0x1d, 0xfd, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-8/ITU",      8, 0x07, 0x00, false, false, 0x55) );
    crc_list.push_back(CRC_Param_Info("CRC-8/MAXIM",    8, 0x31, 0x00, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-8/ROHC",     8, 0x07, 0xff, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-8/WCDMA",    8, 0x9b, 0x00, true,  true,  0x0) );

    // CRC-10
    crc_list.push_back(CRC_Param_Info("CRC-10",          10, 0x233, 0x000, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-10/CDMA2000", 10, 0x3d9, 0x3ff, false, false, 0x0) );

    // CRC-11
    crc_list.push_back(CRC_Param_Info("CRC-11", 11, 0x385, 0x01a, false, false, 0x0) );

    // CRC-12
    crc_list.push_back(CRC_Param_Info("CRC-12/3GPP",     12, 0x80f, 0x000, false, true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-12/CDMA2000", 12, 0xf13, 0xfff, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-12/DECT",     12, 0x80f, 0x000, false, false, 0x0) );

    // CRC-13
    crc_list.push_back(CRC_Param_Info("CRC-13/BBC", 13, 0x1cf5, 0x0, false, false, 0x0) );

    // CRC-14
    crc_list.push_back(CRC_Param_Info("CRC-14/DARC", 14, 0x0805, 0x0, true, true, 0x0) );

    // CRC-15
    crc_list.push_back(CRC_Param_Info("CRC-15",         15, 0x4599, 0x0, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-15/MPT1327", 15, 0x6815, 0x0, false, false, 0x1) );

    // CRC-16
    crc_list.push_back(CRC_Param_Info("CRC-16/ARC",         16, 0x8005, 0x0000, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/AUG-CCITT",   16, 0x1021, 0x1d0f, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/BUYPASS",     16, 0x8005, 0x0000, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/CCITT-FALSE", 16, 0x1021, 0xffff, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/CDMA2000",    16, 0xc867, 0xffff, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/DDS-110",     16, 0x8005, 0x800d, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/DECT-R",      16, 0x0589, 0x0000, false, false, 0x1) );
    crc_list.push_back(CRC_Param_Info("CRC-16/DECT-X",      16, 0x0589, 0x0000, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/DNP",         16, 0x3d65, 0x0000, true,  true,  0xffff) );
    crc_list.push_back(CRC_Param_Info("CRC-16/EN-13757",    16, 0x3d65, 0x0000, false, false, 0xffff) );
    crc_list.push_back(CRC_Param_Info("CRC-16/GENIBUS",     16, 0x1021, 0xffff, false, false, 0xffff) );
    crc_list.push_back(CRC_Param_Info("CRC-16/MAXIM",       16, 0x8005, 0x0000, true,  true,  0xffff) );
    crc_list.push_back(CRC_Param_Info("CRC-16/MCRF4XX",     16, 0x1021, 0xffff, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/RIELLO",      16, 0x1021, 0xb2aa, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/T10-DIF",     16, 0x8bb7, 0x0000, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/TELEDISK",    16, 0xa097, 0x0000, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/TMS37157",    16, 0x1021, 0x89ec, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/USB",         16, 0x8005, 0xffff, true,  true,  0xffff) );
    crc_list.push_back(CRC_Param_Info("CRC-A",              16, 0x1021, 0xc6c6, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/KERMIT",      16, 0x1021, 0x0000, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/MODBUS",      16, 0x8005, 0xffff, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-16/X-25",        16, 0x1021, 0xffff, true,  true,  0xffff) );
    crc_list.push_back(CRC_Param_Info("CRC-16/XMODEM",      16, 0x1021, 0x0000, false, false, 0x0) );

    // CRC-24
    crc_list.push_back(CRC_Param_Info("CRC-24",           24, 0x864cfb, 0xb704ce, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-24/FLEXRAY-A", 24, 0x5d6dcb, 0xfedcba, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-24/FLEXRAY-B", 24, 0x5d6dcb, 0xabcdef, false, false, 0x0) );

    // CRC-31
    crc_list.push_back(CRC_Param_Info("CRC-31/PHILIPS", 31, 0x04c11db7, 0x7fffffff, false, false, 0x7fffffff) );

    // CRC-32
    crc_list.push_back(CRC_Param_Info("CRC-32",       32, 0x04c11db7, 0xffffffff, true,  true,  0xffffffff) );
    crc_list.push_back(CRC_Param_Info("CRC-32/BZIP2", 32, 0x04c11db7, 0xffffffff, false, false, 0xffffffff) );
    crc_list.push_back(CRC_Param_Info("CRC-32C",      32, 0x1edc6f41, 0xffffffff, true,  true,  0xffffffff) );
    crc_list.push_back(CRC_Param_Info("CRC-32D",      32, 0xa833982b, 0xffffffff, true,  true,  0xffffffff) );
    crc_list.push_back(CRC_Param_Info("CRC-32/MPEG-2",32, 0x04c11db7, 0xffffffff, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-32/POSIX", 32, 0x04c11db7, 0x00000000, false, false, 0xffffffff) );
    crc_list.push_back(CRC_Param_Info("CRC-32Q",      32, 0x814141ab, 0x00000000, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-32/JAMCRC",32, 0x04c11db7, 0xffffffff, true,  true,  0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-32/XFER",  32, 0x000000af, 0x00000000, false, false, 0x0) );

    // CRC-40
    crc_list.push_back(CRC_Param_Info("CRC-40/GSM", 40, 0x0004820009, 0x0, false, false, 0xffffffffff) );

    // CRC-64
    crc_list.push_back(CRC_Param_Info("CRC-64",    64, 0x42f0e1eba9ea3693, 0x0000000000000000, false, false, 0x0) );
    crc_list.push_back(CRC_Param_Info("CRC-64/WE", 64, 0x42f0e1eba9ea3693, 0xffffffffffffffff, false, false, 0xffffffffffffffff) );
    crc_list.push_back(CRC_Param_Info("CRC-64/XZ", 64, 0x42f0e1eba9ea3693, 0xffffffffffffffff, true,  true,  0xffffffffffffffff) );

    return crc_list;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
#include "webrtc/modules/video_coding/main/source/generic_encoder.h"
#include "webrtc/modules/video_coding/main/source/media_optimization.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"

namespace webrtc {
namespace {
// Map information from info into rtp. If no relevant information is found
// in info, rtp is set to NULL.
void CopyCodecSpecific(const CodecSpecificInfo* info, RTPVideoHeader** rtp) {
  if (!info) {
    *rtp = NULL;
    return;
  }
  switch (info->codecType) {
    case kVideoCodecVP8: {
      (*rtp)->codec = kRtpVideoVp8;
      (*rtp)->codecHeader.VP8.InitRTPVideoHeaderVP8();
      (*rtp)->codecHeader.VP8.pictureId = info->codecSpecific.VP8.pictureId;
      (*rtp)->codecHeader.VP8.nonReference =
          info->codecSpecific.VP8.nonReference;
      (*rtp)->codecHeader.VP8.temporalIdx = info->codecSpecific.VP8.temporalIdx;
      (*rtp)->codecHeader.VP8.layerSync = info->codecSpecific.VP8.layerSync;
      (*rtp)->codecHeader.VP8.tl0PicIdx = info->codecSpecific.VP8.tl0PicIdx;
      (*rtp)->codecHeader.VP8.keyIdx = info->codecSpecific.VP8.keyIdx;
      (*rtp)->simulcastIdx = info->codecSpecific.VP8.simulcastIdx;
      return;
    }
    case kVideoCodecH264:
      (*rtp)->codec = kRtpVideoH264;
      return;
    case kVideoCodecGeneric:
      (*rtp)->codec = kRtpVideoGeneric;
      (*rtp)->simulcastIdx = info->codecSpecific.generic.simulcast_idx;
      return;
    default:
      // No codec specific info. Change RTP header pointer to NULL.
      *rtp = NULL;
      return;
  }
}
}  // namespace

//#define DEBUG_ENCODER_BIT_STREAM

VCMGenericEncoder::VCMGenericEncoder(VideoEncoder& encoder, bool internalSource /*= false*/)
:
_encoder(encoder),
_codecType(kVideoCodecUnknown),
_VCMencodedFrameCallback(NULL),
_bitRate(0),
_frameRate(0),
_internalSource(internalSource)
{
}

VCMGenericEncoder::~VCMGenericEncoder()
{
}

int32_t VCMGenericEncoder::Release()
{
    _bitRate = 0;
    _frameRate = 0;
    _VCMencodedFrameCallback = NULL;
    return _encoder.Release();
}

int32_t
VCMGenericEncoder::InitEncode(const VideoCodec* settings,
                              int32_t numberOfCores,
                              size_t maxPayloadSize)
{
    _bitRate = settings->startBitrate * 1000;
    _frameRate = settings->maxFramerate;
    _codecType = settings->codecType;
    if (_encoder.InitEncode(settings, numberOfCores, maxPayloadSize) != 0) {
      LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
                       "payload name: " << settings->plName;
      return -1;
    }
    return 0;
}

int32_t
VCMGenericEncoder::Encode(const I420VideoFrame& inputFrame,
                          const CodecSpecificInfo* codecSpecificInfo,
                          const std::vector<FrameType>& frameTypes) {
  std::vector<VideoFrameType> video_frame_types(frameTypes.size(),
                                                kDeltaFrame);
  VCMEncodedFrame::ConvertFrameTypes(frameTypes, &video_frame_types);
  return _encoder.Encode(inputFrame, codecSpecificInfo, &video_frame_types);
}

int32_t
VCMGenericEncoder::SetChannelParameters(int32_t packetLoss, int64_t rtt)
{
    return _encoder.SetChannelParameters(packetLoss, rtt);
}

int32_t
VCMGenericEncoder::SetRates(uint32_t newBitRate, uint32_t frameRate)
{
    uint32_t target_bitrate_kbps = (newBitRate + 500) / 1000;
    int32_t ret = _encoder.SetRates(target_bitrate_kbps, frameRate);
    if (ret < 0)
    {
        return ret;
    }
    _bitRate = newBitRate;
    _frameRate = frameRate;
    return VCM_OK;
}

int32_t
VCMGenericEncoder::CodecConfigParameters(uint8_t* buffer, int32_t size)
{
    int32_t ret = _encoder.CodecConfigParameters(buffer, size);
    if (ret < 0)
    {
        return ret;
    }
    return ret;
}

uint32_t VCMGenericEncoder::BitRate() const
{
    return _bitRate;
}

uint32_t VCMGenericEncoder::FrameRate() const
{
    return _frameRate;
}

int32_t
VCMGenericEncoder::SetPeriodicKeyFrames(bool enable)
{
    return _encoder.SetPeriodicKeyFrames(enable);
}

int32_t VCMGenericEncoder::RequestFrame(
    const std::vector<FrameType>& frame_types) {
  I420VideoFrame image;
  std::vector<VideoFrameType> video_frame_types(frame_types.size(),
                                                kDeltaFrame);
  VCMEncodedFrame::ConvertFrameTypes(frame_types, &video_frame_types);
  return _encoder.Encode(image, NULL, &video_frame_types);
}

int32_t
VCMGenericEncoder::RegisterEncodeCallback(VCMEncodedFrameCallback* VCMencodedFrameCallback)
{
   _VCMencodedFrameCallback = VCMencodedFrameCallback;
   _VCMencodedFrameCallback->SetInternalSource(_internalSource);
   return _encoder.RegisterEncodeCompleteCallback(_VCMencodedFrameCallback);
}

bool
VCMGenericEncoder::InternalSource() const
{
    return _internalSource;
}

 /***************************
  * Callback Implementation
  ***************************/
VCMEncodedFrameCallback::VCMEncodedFrameCallback(
    EncodedImageCallback* post_encode_callback):
_sendCallback(),
_mediaOpt(NULL),
_payloadType(0),
_internalSource(false),
post_encode_callback_(post_encode_callback)
#ifdef DEBUG_ENCODER_BIT_STREAM
, _bitStreamAfterEncoder(NULL)
#endif
{
#ifdef DEBUG_ENCODER_BIT_STREAM
    _bitStreamAfterEncoder = fopen("encoderBitStream.bit", "wb");
#endif
}

VCMEncodedFrameCallback::~VCMEncodedFrameCallback()
{
#ifdef DEBUG_ENCODER_BIT_STREAM
    fclose(_bitStreamAfterEncoder);
#endif
}

int32_t
VCMEncodedFrameCallback::SetTransportCallback(VCMPacketizationCallback* transport)
{
    _sendCallback = transport;
    return VCM_OK;
}

int32_t VCMEncodedFrameCallback::Encoded(
    const EncodedImage& encodedImage,
    const CodecSpecificInfo* codecSpecificInfo,
    const RTPFragmentationHeader* fragmentationHeader) {
  post_encode_callback_->Encoded(encodedImage, NULL, NULL);

  if (_sendCallback == NULL) {
    return VCM_UNINITIALIZED;
  }

#ifdef DEBUG_ENCODER_BIT_STREAM
  if (_bitStreamAfterEncoder != NULL) {
    fwrite(encodedImage._buffer, 1, encodedImage._length,
           _bitStreamAfterEncoder);
  }
#endif

  RTPVideoHeader rtpVideoHeader;
  RTPVideoHeader* rtpVideoHeaderPtr = &rtpVideoHeader;
  CopyCodecSpecific(codecSpecificInfo, &rtpVideoHeaderPtr);

  int32_t callbackReturn = _sendCallback->SendData(
      _payloadType, encodedImage, *fragmentationHeader, rtpVideoHeaderPtr);
  if (callbackReturn < 0) {
    return callbackReturn;
  }

  if (_mediaOpt != NULL) {
    _mediaOpt->UpdateWithEncodedData(encodedImage);
    if (_internalSource)
      return _mediaOpt->DropFrame();  // Signal to encoder to drop next frame.
  }
  return VCM_OK;
}

void
VCMEncodedFrameCallback::SetMediaOpt(
    media_optimization::MediaOptimization *mediaOpt)
{
    _mediaOpt = mediaOpt;
}

}  // namespace webrtc
<commit_msg>Initialize RTPVideoHeader fields to correctly set simulcastIdx for non VP8 codecs.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
#include "webrtc/modules/video_coding/main/source/generic_encoder.h"
#include "webrtc/modules/video_coding/main/source/media_optimization.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"

namespace webrtc {
namespace {
// Map information from info into rtp. If no relevant information is found
// in info, rtp is set to NULL.
void CopyCodecSpecific(const CodecSpecificInfo* info, RTPVideoHeader** rtp) {
  if (!info) {
    *rtp = NULL;
    return;
  }
  switch (info->codecType) {
    case kVideoCodecVP8: {
      (*rtp)->codec = kRtpVideoVp8;
      (*rtp)->codecHeader.VP8.InitRTPVideoHeaderVP8();
      (*rtp)->codecHeader.VP8.pictureId = info->codecSpecific.VP8.pictureId;
      (*rtp)->codecHeader.VP8.nonReference =
          info->codecSpecific.VP8.nonReference;
      (*rtp)->codecHeader.VP8.temporalIdx = info->codecSpecific.VP8.temporalIdx;
      (*rtp)->codecHeader.VP8.layerSync = info->codecSpecific.VP8.layerSync;
      (*rtp)->codecHeader.VP8.tl0PicIdx = info->codecSpecific.VP8.tl0PicIdx;
      (*rtp)->codecHeader.VP8.keyIdx = info->codecSpecific.VP8.keyIdx;
      (*rtp)->simulcastIdx = info->codecSpecific.VP8.simulcastIdx;
      return;
    }
    case kVideoCodecH264:
      (*rtp)->codec = kRtpVideoH264;
      return;
    case kVideoCodecGeneric:
      (*rtp)->codec = kRtpVideoGeneric;
      (*rtp)->simulcastIdx = info->codecSpecific.generic.simulcast_idx;
      return;
    default:
      // No codec specific info. Change RTP header pointer to NULL.
      *rtp = NULL;
      return;
  }
}
}  // namespace

//#define DEBUG_ENCODER_BIT_STREAM

VCMGenericEncoder::VCMGenericEncoder(VideoEncoder& encoder, bool internalSource /*= false*/)
:
_encoder(encoder),
_codecType(kVideoCodecUnknown),
_VCMencodedFrameCallback(NULL),
_bitRate(0),
_frameRate(0),
_internalSource(internalSource)
{
}

VCMGenericEncoder::~VCMGenericEncoder()
{
}

int32_t VCMGenericEncoder::Release()
{
    _bitRate = 0;
    _frameRate = 0;
    _VCMencodedFrameCallback = NULL;
    return _encoder.Release();
}

int32_t
VCMGenericEncoder::InitEncode(const VideoCodec* settings,
                              int32_t numberOfCores,
                              size_t maxPayloadSize)
{
    _bitRate = settings->startBitrate * 1000;
    _frameRate = settings->maxFramerate;
    _codecType = settings->codecType;
    if (_encoder.InitEncode(settings, numberOfCores, maxPayloadSize) != 0) {
      LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
                       "payload name: " << settings->plName;
      return -1;
    }
    return 0;
}

int32_t
VCMGenericEncoder::Encode(const I420VideoFrame& inputFrame,
                          const CodecSpecificInfo* codecSpecificInfo,
                          const std::vector<FrameType>& frameTypes) {
  std::vector<VideoFrameType> video_frame_types(frameTypes.size(),
                                                kDeltaFrame);
  VCMEncodedFrame::ConvertFrameTypes(frameTypes, &video_frame_types);
  return _encoder.Encode(inputFrame, codecSpecificInfo, &video_frame_types);
}

int32_t
VCMGenericEncoder::SetChannelParameters(int32_t packetLoss, int64_t rtt)
{
    return _encoder.SetChannelParameters(packetLoss, rtt);
}

int32_t
VCMGenericEncoder::SetRates(uint32_t newBitRate, uint32_t frameRate)
{
    uint32_t target_bitrate_kbps = (newBitRate + 500) / 1000;
    int32_t ret = _encoder.SetRates(target_bitrate_kbps, frameRate);
    if (ret < 0)
    {
        return ret;
    }
    _bitRate = newBitRate;
    _frameRate = frameRate;
    return VCM_OK;
}

int32_t
VCMGenericEncoder::CodecConfigParameters(uint8_t* buffer, int32_t size)
{
    int32_t ret = _encoder.CodecConfigParameters(buffer, size);
    if (ret < 0)
    {
        return ret;
    }
    return ret;
}

uint32_t VCMGenericEncoder::BitRate() const
{
    return _bitRate;
}

uint32_t VCMGenericEncoder::FrameRate() const
{
    return _frameRate;
}

int32_t
VCMGenericEncoder::SetPeriodicKeyFrames(bool enable)
{
    return _encoder.SetPeriodicKeyFrames(enable);
}

int32_t VCMGenericEncoder::RequestFrame(
    const std::vector<FrameType>& frame_types) {
  I420VideoFrame image;
  std::vector<VideoFrameType> video_frame_types(frame_types.size(),
                                                kDeltaFrame);
  VCMEncodedFrame::ConvertFrameTypes(frame_types, &video_frame_types);
  return _encoder.Encode(image, NULL, &video_frame_types);
}

int32_t
VCMGenericEncoder::RegisterEncodeCallback(VCMEncodedFrameCallback* VCMencodedFrameCallback)
{
   _VCMencodedFrameCallback = VCMencodedFrameCallback;
   _VCMencodedFrameCallback->SetInternalSource(_internalSource);
   return _encoder.RegisterEncodeCompleteCallback(_VCMencodedFrameCallback);
}

bool
VCMGenericEncoder::InternalSource() const
{
    return _internalSource;
}

 /***************************
  * Callback Implementation
  ***************************/
VCMEncodedFrameCallback::VCMEncodedFrameCallback(
    EncodedImageCallback* post_encode_callback):
_sendCallback(),
_mediaOpt(NULL),
_payloadType(0),
_internalSource(false),
post_encode_callback_(post_encode_callback)
#ifdef DEBUG_ENCODER_BIT_STREAM
, _bitStreamAfterEncoder(NULL)
#endif
{
#ifdef DEBUG_ENCODER_BIT_STREAM
    _bitStreamAfterEncoder = fopen("encoderBitStream.bit", "wb");
#endif
}

VCMEncodedFrameCallback::~VCMEncodedFrameCallback()
{
#ifdef DEBUG_ENCODER_BIT_STREAM
    fclose(_bitStreamAfterEncoder);
#endif
}

int32_t
VCMEncodedFrameCallback::SetTransportCallback(VCMPacketizationCallback* transport)
{
    _sendCallback = transport;
    return VCM_OK;
}

int32_t VCMEncodedFrameCallback::Encoded(
    const EncodedImage& encodedImage,
    const CodecSpecificInfo* codecSpecificInfo,
    const RTPFragmentationHeader* fragmentationHeader) {
  post_encode_callback_->Encoded(encodedImage, NULL, NULL);

  if (_sendCallback == NULL) {
    return VCM_UNINITIALIZED;
  }

#ifdef DEBUG_ENCODER_BIT_STREAM
  if (_bitStreamAfterEncoder != NULL) {
    fwrite(encodedImage._buffer, 1, encodedImage._length,
           _bitStreamAfterEncoder);
  }
#endif

  RTPVideoHeader rtpVideoHeader;
  memset(&rtpVideoHeader, 0, sizeof(RTPVideoHeader));
  RTPVideoHeader* rtpVideoHeaderPtr = &rtpVideoHeader;
  CopyCodecSpecific(codecSpecificInfo, &rtpVideoHeaderPtr);

  int32_t callbackReturn = _sendCallback->SendData(
      _payloadType, encodedImage, *fragmentationHeader, rtpVideoHeaderPtr);
  if (callbackReturn < 0) {
    return callbackReturn;
  }

  if (_mediaOpt != NULL) {
    _mediaOpt->UpdateWithEncodedData(encodedImage);
    if (_internalSource)
      return _mediaOpt->DropFrame();  // Signal to encoder to drop next frame.
  }
  return VCM_OK;
}

void
VCMEncodedFrameCallback::SetMediaOpt(
    media_optimization::MediaOptimization *mediaOpt)
{
    _mediaOpt = mediaOpt;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/*
 * RondomAttributizer.cpp
 *
 *  Created on: 11.08.2014
 *      Author: Gerd Lindner
 */

#include "RandomAttributizer.h"

namespace NetworKit {

RandomAttributizer::RandomAttributizer(const Graph& graph) : graph(graph) {
}

std::vector<double> RandomAttributizer::getAttribute() {
	if (!graph.hasEdgeIds()) {
		throw std::runtime_error("edges have not been indexed - call indexEdges first");
	}

	std::vector<double> randomAttribute(graph.upperEdgeIdBound(), 0.0);

	graph.forEdges([&](node u, node v, edgeid eid) {
		//double r = Aux::Random::probability();
		//randomAttribute[eid] = randomness * r + (1 - randomness) * attribute[eid];
		randomAttribute[eid] = Aux::Random::probability();
	});

	return randomAttribute;
}

} /* namespace NetworKit */
<commit_msg>RandomAttributizer parallelization<commit_after>/*
 * RondomAttributizer.cpp
 *
 *  Created on: 11.08.2014
 *      Author: Gerd Lindner
 */

#include "RandomAttributizer.h"

namespace NetworKit {

RandomAttributizer::RandomAttributizer(const Graph& graph) : graph(graph) {
}

std::vector<double> RandomAttributizer::getAttribute() {
	if (!graph.hasEdgeIds()) {
		throw std::runtime_error("edges have not been indexed - call indexEdges first");
	}

	std::vector<double> randomAttribute(graph.upperEdgeIdBound(), 0.0);

	graph.parallelForEdges([&](node u, node v, edgeid eid) {
		//double r = Aux::Random::probability();
		//randomAttribute[eid] = randomness * r + (1 - randomness) * attribute[eid];
		randomAttribute[eid] = Aux::Random::probability();
	});

	return randomAttribute;
}

} /* namespace NetworKit */
<|endoftext|>


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

#ifndef FLTL_SYMBOL_HPP_
#define FLTL_SYMBOL_HPP_

namespace fltl { namespace cfg {

    /// grammar symbol (non-terminal or terminal)
    template <typename AlphaT>
    class Symbol {
    protected:

        mutable internal_sym_type value;

        friend class CFG<AlphaT>;
        friend class Variable<AlphaT>;
        friend class Production<AlphaT>;
        friend class OpaqueProduction<AlphaT>;
        friend class ProductionBuilder<AlphaT>;
        friend class SymbolString<AlphaT>;
        friend class VariableSymbol<AlphaT>;
        friend class TerminalSymbol<AlphaT>;
        friend class detail::SimpleGenerator<AlphaT>;
        friend class detail::PatternData<AlphaT>;

        template <typename, typename>
        friend class detail::PatternGenerator;

        typedef SymbolString<AlphaT> symbol_string_type;

        /// adapted from fmix32, from Murmurhash3, by Austin Appleby.
        // this function is adapted from code that is licensed under the
        // MIT license
        inline static internal_sym_type
        mix32(const internal_sym_type _value) throw() {
            uint32_t h(static_cast<uint32_t>(_value));
            h ^= h >> 16;
            h *= 0x85ebca6b;
            h ^= h >> 13;
            h *= 0xc2b2ae35;
            h ^= h >> 16;
            return static_cast<internal_sym_type>(h);
        }

        FLTL_FORCE_INLINE internal_sym_type
        hash(void) const throw() {
            return mix32(value);
        }

        typedef Symbol<AlphaT> self_type;

        explicit Symbol(const internal_sym_type _value) throw()
            : value(_value)
        { }

    public:

        Symbol(void) throw()
            : value(1)
        { }

        Symbol(const self_type &that) throw()
            : value(that.value)
        { }

        ~Symbol(void) { }

        inline self_type &operator=(const self_type &that) throw() {
            value = that.value;
            return *this;
        }

        FLTL_FORCE_INLINE bool
        operator==(const self_type &that) const throw() {
            return value == that.value;
        }

        FLTL_FORCE_INLINE bool
        operator!=(const self_type &that) const throw() {
            return value != that.value;
        }

        inline bool operator==(const symbol_string_type &that) const throw() {
            return (
                length() == that.length() && hash() == that.get_hash()
            );
        }

        inline bool operator!=(const symbol_string_type &that) const throw() {
            return (
                length() != that.length() || hash() != that.get_hash()
            );
        }

        inline unsigned length(void) const throw() {
            return 1U;
        }

        /// concatenate this symbol with a symbol string, i.e. prepend this
        /// symbol onto the beginning of the other symbol string and return
        /// the result
        FLTL_FORCE_INLINE const symbol_string_type
        operator+(symbol_string_type that) const throw() {
            return that.prepend_symbol(this);
        }

        /// concatenate this symbol with another symbol and return the symbol
        /// string.
        const symbol_string_type
        operator+(const self_type that) const throw() {
            symbol_string_type ret;
            const unsigned this_len = length();
            const unsigned that_len = that.length();
            const unsigned total_len(this_len + that_len);

            if(0 == total_len) {
                return ret;
            }

            ret.symbols = symbol_string_type::allocate(total_len);
            ret.symbols[str::FIRST_SYMBOL].value = value;
            ret.symbols[
                str::FIRST_SYMBOL + this_len
            ].value = that.value;

            if(0 == this_len) {
                ret.symbols[str::HASH].value = that.hash();
            } else if(0 == that_len) {
                ret.symbols[str::HASH].value = hash();
            } else {
                ret.symbols[str::HASH].value = (
                    symbol_string_type::hash(
                        hash(),
                        that.hash()
                    )
                );
            }

            return ret;
        }

        /// is this a variable?
        FLTL_FORCE_INLINE bool is_variable(void) const throw() {
            return value > 0;
        }

        /// is this a terminal?
        FLTL_FORCE_INLINE bool is_terminal(void) const throw() {
            return value < 0;
        }

        unsigned number(void) const throw() {
            if(value < 0) {
                return static_cast<unsigned>(value * -1);
            } else {
                return static_cast<unsigned>(value);
            }
        }

        /// return an "unbound" version of this symbol
        /// note: *not* const!!
        Unbound<AlphaT,symbol_tag> operator~(void) throw() {
            return Unbound<AlphaT,symbol_tag>(this);
        }
    };

}}

#endif /* FLTL_SYMBOL_HPP_ */
<commit_msg>vc++ is warning about some things that have already been declared...<commit_after>/*
 * Symbol.hpp
 *
 *  Created on: Jan 20, 2011
 *      Author: Peter Goodman
 *     Version: $Id$
 *
 * Copyright 2011 Peter Goodman, all rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef FLTL_SYMBOL_HPP_
#define FLTL_SYMBOL_HPP_

namespace fltl {
    template <typename> class CFG;
    template <typename> class Variable;
    template <typename> class Production;
    template <typename> class OpaqueProduction;
    template <typename> class ProductionBuilder;
    template <typename> class SymbolString;
    template <typename> class VariableSymbol;
    template <typename> class TerminalSymbol;

    namespace detail {
        template <typename> class SimpleGenerator;
        template <typename> class PatternData;
        template <typename,typename> class PatternGenerator;
    }
}

namespace fltl { namespace cfg {

    /// grammar symbol (non-terminal or terminal)
    template <typename AlphaT>
    class Symbol {
    protected:

        mutable internal_sym_type value;

        friend class CFG<AlphaT>;
        friend class Variable<AlphaT>;
        friend class Production<AlphaT>;
        friend class OpaqueProduction<AlphaT>;
        friend class ProductionBuilder<AlphaT>;
        friend class SymbolString<AlphaT>;
        friend class VariableSymbol<AlphaT>;
        friend class TerminalSymbol<AlphaT>;
        friend class detail::SimpleGenerator<AlphaT>;
        friend class detail::PatternData<AlphaT>;

        template <typename, typename>
        friend class detail::PatternGenerator;

        typedef SymbolString<AlphaT> symbol_string_type;

        /// adapted from fmix32, from Murmurhash3, by Austin Appleby.
        // this function is adapted from code that is licensed under the
        // MIT license
        inline static internal_sym_type
        mix32(const internal_sym_type _value) throw() {
            uint32_t h(static_cast<uint32_t>(_value));
            h ^= h >> 16;
            h *= 0x85ebca6b;
            h ^= h >> 13;
            h *= 0xc2b2ae35;
            h ^= h >> 16;
            return static_cast<internal_sym_type>(h);
        }

        FLTL_FORCE_INLINE internal_sym_type
        hash(void) const throw() {
            return mix32(value);
        }

        typedef Symbol<AlphaT> self_type;

        explicit Symbol(const internal_sym_type _value) throw()
            : value(_value)
        { }

    public:

        Symbol(void) throw()
            : value(1)
        { }

        Symbol(const self_type &that) throw()
            : value(that.value)
        { }

        ~Symbol(void) { }

        inline self_type &operator=(const self_type &that) throw() {
            value = that.value;
            return *this;
        }

        FLTL_FORCE_INLINE bool
        operator==(const self_type &that) const throw() {
            return value == that.value;
        }

        FLTL_FORCE_INLINE bool
        operator!=(const self_type &that) const throw() {
            return value != that.value;
        }

        inline bool operator==(const symbol_string_type &that) const throw() {
            return (
                length() == that.length() && hash() == that.get_hash()
            );
        }

        inline bool operator!=(const symbol_string_type &that) const throw() {
            return (
                length() != that.length() || hash() != that.get_hash()
            );
        }

        inline unsigned length(void) const throw() {
            return 1U;
        }

        /// concatenate this symbol with a symbol string, i.e. prepend this
        /// symbol onto the beginning of the other symbol string and return
        /// the result
        FLTL_FORCE_INLINE const symbol_string_type
        operator+(symbol_string_type that) const throw() {
            return that.prepend_symbol(this);
        }

        /// concatenate this symbol with another symbol and return the symbol
        /// string.
        const symbol_string_type
        operator+(const self_type that) const throw() {
            symbol_string_type ret;
            const unsigned this_len = length();
            const unsigned that_len = that.length();
            const unsigned total_len(this_len + that_len);

            if(0 == total_len) {
                return ret;
            }

            ret.symbols = symbol_string_type::allocate(total_len);
            ret.symbols[str::FIRST_SYMBOL].value = value;
            ret.symbols[
                str::FIRST_SYMBOL + this_len
            ].value = that.value;

            if(0 == this_len) {
                ret.symbols[str::HASH].value = that.hash();
            } else if(0 == that_len) {
                ret.symbols[str::HASH].value = hash();
            } else {
                ret.symbols[str::HASH].value = (
                    symbol_string_type::hash(
                        hash(),
                        that.hash()
                    )
                );
            }

            return ret;
        }

        /// is this a variable?
        FLTL_FORCE_INLINE bool is_variable(void) const throw() {
            return value > 0;
        }

        /// is this a terminal?
        FLTL_FORCE_INLINE bool is_terminal(void) const throw() {
            return value < 0;
        }

        unsigned number(void) const throw() {
            if(value < 0) {
                return static_cast<unsigned>(value * -1);
            } else {
                return static_cast<unsigned>(value);
            }
        }

        /// return an "unbound" version of this symbol
        /// note: *not* const!!
        Unbound<AlphaT,symbol_tag> operator~(void) throw() {
            return Unbound<AlphaT,symbol_tag>(this);
        }
    };

}}

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