<commit_before>//=============================================================================================================
/**
* @file     rtsss.cpp
* @author   Seok Lew <slew@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     February, 2013
*
* @section  LICENSE
*
* Copyright (C) 2013, Christoph Dinh and Matti Hamalainen. 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 the Massachusetts General Hospital 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 MASSACHUSETTS GENERAL HOSPITAL BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Contains the implementation of the RtSss class.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "rtsss.h"
#include "FormFiles/rtssssetupwidget.h"
#include "rtsssalgo.h"

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

#include <QtCore/QtPlugin>
#include <QDebug>

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

using namespace RtSssPlugin;
using namespace FIFFLIB;
using namespace MNEX;
using namespace XMEASLIB;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

RtSss::RtSss()
: m_bIsRunning(false)
, m_bReceiveData(false)
, m_bProcessData(false)
//, m_pRTSAInput(NULL)
//, m_pRTSAOutput(NULL)
//, m_pRtSssBuffer(new dBuffer(1024))
{
}

//*************************************************************************************************************

RtSss::~RtSss()
{
    stop();
}

//*************************************************************************************************************

QSharedPointer<IPlugin> RtSss::clone() const
{
    QSharedPointer<RtSss> pRtSssClone(new RtSss);
    return pRtSssClone;
}

//*************************************************************************************************************
//=============================================================================================================
// Creating required display instances and set configurations
//=============================================================================================================

void RtSss::init()
{
    std::cout << "*********** Initialization ************" << std::endl;

    //Delete Buffer - will be initailzed with first incoming data
    if(!m_pRtSssBuffer.isNull())
        m_pRtSssBuffer = CircularMatrixBuffer<double>::SPtr();

    // Input
    m_pRTMSAInput = PluginInputData<NewRealTimeMultiSampleArray>::create(this, "RtSssIn", "RtSss input data");
    connect(m_pRTMSAInput.data(), &PluginInputConnector::notify, this, &RtSss::update, Qt::DirectConnection);
    m_inputConnectors.append(m_pRTMSAInput);

    // Output
    m_pRTMSAOutput = PluginOutputData<NewRealTimeMultiSampleArray>::create(this, "RtSssOut", "RtSss output data");
    m_outputConnectors.append(m_pRTMSAOutput);
}

//*************************************************************************************************************

bool RtSss::start()
{
    std::cout << "*********** Start ************" << std::endl;

    QThread::start();
    return true;
}

//*************************************************************************************************************

bool RtSss::stop()
{
    std::cout << "*********** Stop ************" << std::endl;

    m_bIsRunning = false;

    // Stop threads
    QThread::terminate();
    QThread::wait();

    if(m_pRtSssBuffer)
        m_pRtSssBuffer->clear();

    m_bReceiveData = false;

    return true;
}

//*************************************************************************************************************

IPlugin::PluginType RtSss::getType() const
{
    return _IAlgorithm;
}

//*************************************************************************************************************

QString RtSss::getName() const
{
    return "RtSss Toolbox";
}

//*************************************************************************************************************

QWidget* RtSss::setupWidget()
{
    std::cout << "*********** SetUpWidget ************" << std::endl;

    RtSssSetupWidget* widget = new RtSssSetupWidget(this);  //widget is later distroyed by CentralWidget - so it has to be created everytime new

    connect(widget, &RtSssSetupWidget::signalNewLinRR, this, &RtSss::setLinRR);
    connect(widget, &RtSssSetupWidget::signalNewLoutRR, this, &RtSss::setLoutRR);
    connect(widget, &RtSssSetupWidget::signalNewLin, this, &RtSss::setLin);
    connect(widget, &RtSssSetupWidget::signalNewLout, this, &RtSss::setLout);

    LinRR = widget->getLinRR();
    LoutRR = widget->getLoutRR();
    Lin = widget->getLin();
    Lout = widget->getLout();

    return widget;
}

void RtSss::setLinRR(int val)
{
//    std::cout <<" new LinRR: " << val << std::endl;
    LinRR = val;
}

void RtSss::setLoutRR(int val)
{
//    std::cout <<" new LoutRR: " << val << std::endl;
    LoutRR = val;
}

void RtSss::setLin(int val)
{
//    std::cout <<" new Lin: " << val << std::endl;
    Lin = val;
}

void RtSss::setLout(int val)
{
//    std::cout <<" new Lout: " << val << std::endl;
    Lout = val;
}

//*************************************************************************************************************

void RtSss::update(XMEASLIB::NewMeasurement::SPtr pMeasurement)
{
//    std::cout << "*********** Update ************" << std::endl;

    QSharedPointer<NewRealTimeMultiSampleArray> pRTMSA = pMeasurement.dynamicCast<NewRealTimeMultiSampleArray>();

    if(pRTMSA && m_bReceiveData)
    {
        //Check if buffer initialized
        if(!m_pRtSssBuffer)
            m_pRtSssBuffer = CircularMatrixBuffer<double>::SPtr(new CircularMatrixBuffer<double>(64, pRTMSA->getNumChannels(), pRTMSA->getMultiArraySize()));

        //Fiff information
        if(!m_pFiffInfo)
            m_pFiffInfo = pRTMSA->getFiffInfo();

        if(m_bProcessData)
        {
            MatrixXd in_mat(pRTMSA->getNumChannels(), pRTMSA->getMultiArraySize());
            for(unsigned char i = 0; i < pRTMSA->getMultiArraySize(); ++i)
                in_mat.col(i) = pRTMSA->getMultiSampleArray()[i];

            m_pRtSssBuffer->push(&in_mat);
        }
    }
}

//*************************************************************************************************************

void RtSss::run()
{

    RtSssAlgo rsss;
    QList<MatrixXd> lineqn, sssRR;

    m_bIsRunning = true;

    //
    // start receiving data
    //
    m_bReceiveData = true;

    // Read Fiff Info
    //
    while(!m_pFiffInfo)
        msleep(10);// Wait for fiff Info

    // Set MEG channel infomation
    rsss.setMEGInfo(m_pFiffInfo);

    // Init output
    m_pRTMSAOutput->data()->initFromFiffInfo(m_pFiffInfo);
    m_pRTMSAOutput->data()->setMultiArraySize(100);
//    m_pRTMSAOutput->data()->setSamplingRate(m_pFiffInfo->sfreq);
    m_pRTMSAOutput->data()->setVisibility(true);

    qDebug() << "LinRR (run): " << LinRR << ", LoutRR (run): " << LoutRR <<", Lin (run): " << Lin <<", Lout (run): " << Lout;
    QList<int> expOrder;
    expOrder << LinRR << LoutRR << Lin << Lout;
    rsss.setSSSParameter(expOrder);

    // Find the number of MEG channel
    qint32 nmegchan = rsss.getNumMEGCh();
//    std::cout << "number of meg channels: " << nmegchan << std::endl;

//    std::cout << "building SSS linear equation .....";
    qDebug() << "building SSS linear equation .....";
    lineqn = rsss.buildLinearEqn();
    qDebug() << " finished (run)!";

    // start processing data
    m_bProcessData = true;

    while(m_bIsRunning)
    {
        qint32 nrows = m_pRtSssBuffer->rows();

        if(nrows > 0) // check if init
        {
            // * Dispatch the inputs * //
            MatrixXd in_mat = m_pRtSssBuffer->pop();
//            std::cout << "size of in_mat (run): " << in_mat.rows() << " x " << in_mat.cols() << std::endl;

            for(qint32 i = 0; i <in_mat.cols(); ++i)
            {
/*
//              When MEG channels don't start from the first row and may be mixed with other channels
                qint32 m = 0;
                MatrixXd meg_mat(nmegchan, 1);
                for(qint32 j = 0; j < in_mat.rows(); ++j)
                    if(m_pFiffInfo->chs[j].kind == FIFFV_MEG_CH)
                    {
                        meg_mat(m,0) = in_mat(j,i);
                        m++;
                    }

//                std::cout << "size meg_mat: " << meg_mat.rows() << " x " << meg_mat.cols() << std::endl;
                  sssRR = rsss.getSSSRR(lineqn[0], lineqn[1], lineqn[2], lineqn[3], lineqn[4]*meg_mat);
*/

//                qDebug() << "running rtSSS .....";
                sssRR = rsss.getSSSRR(lineqn[0], lineqn[1], lineqn[2], lineqn[3], lineqn[4]*in_mat.block(0,i,nmegchan,1));
                in_mat.block(0,i,nmegchan,1) = sssRR[0];
                m_pRTMSAOutput->data()->setValue(in_mat.col(i));
            }
        }
    }

    m_bProcessData = false;
    m_bReceiveData = false;

}

<commit_msg>update<commit_after>//=============================================================================================================
/**
* @file     rtsss.cpp
* @author   Seok Lew <slew@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     February, 2013
*
* @section  LICENSE
*
* Copyright (C) 2013, Christoph Dinh and Matti Hamalainen. 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 the Massachusetts General Hospital 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 MASSACHUSETTS GENERAL HOSPITAL BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Contains the implementation of the RtSss class.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "rtsss.h"
#include "FormFiles/rtssssetupwidget.h"
#include "rtsssalgo.h"

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

#include <QtCore/QtPlugin>
#include <QDebug>
#include <QFuture>
#include <QtConcurrent/QtConcurrentMap>

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

using namespace RtSssPlugin;
using namespace FIFFLIB;
using namespace MNEX;
using namespace XMEASLIB;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

RtSss::RtSss()
: m_bIsRunning(false)
, m_bReceiveData(false)
, m_bProcessData(false)
//, m_pRTSAInput(NULL)
//, m_pRTSAOutput(NULL)
//, m_pRtSssBuffer(new dBuffer(1024))
{
}

//*************************************************************************************************************

RtSss::~RtSss()
{
    stop();
}

//*************************************************************************************************************

QSharedPointer<IPlugin> RtSss::clone() const
{
    QSharedPointer<RtSss> pRtSssClone(new RtSss);
    return pRtSssClone;
}

//*************************************************************************************************************
//=============================================================================================================
// Creating required display instances and set configurations
//=============================================================================================================

void RtSss::init()
{
    std::cout << "*********** Initialization ************" << std::endl;

    //Delete Buffer - will be initailzed with first incoming data
    if(!m_pRtSssBuffer.isNull())
        m_pRtSssBuffer = CircularMatrixBuffer<double>::SPtr();

    // Input
    m_pRTMSAInput = PluginInputData<NewRealTimeMultiSampleArray>::create(this, "RtSssIn", "RtSss input data");
    connect(m_pRTMSAInput.data(), &PluginInputConnector::notify, this, &RtSss::update, Qt::DirectConnection);
    m_inputConnectors.append(m_pRTMSAInput);

    // Output
    m_pRTMSAOutput = PluginOutputData<NewRealTimeMultiSampleArray>::create(this, "RtSssOut", "RtSss output data");
    m_outputConnectors.append(m_pRTMSAOutput);
}

//*************************************************************************************************************

bool RtSss::start()
{
    std::cout << "*********** Start ************" << std::endl;

    QThread::start();
    return true;
}

//*************************************************************************************************************

bool RtSss::stop()
{
    std::cout << "*********** Stop ************" << std::endl;

    m_bIsRunning = false;

    // Stop threads
    QThread::terminate();
    QThread::wait();

    if(m_pRtSssBuffer)
        m_pRtSssBuffer->clear();

    m_bReceiveData = false;

    return true;
}

//*************************************************************************************************************

IPlugin::PluginType RtSss::getType() const
{
    return _IAlgorithm;
}

//*************************************************************************************************************

QString RtSss::getName() const
{
    return "RtSss Toolbox";
}

//*************************************************************************************************************

QWidget* RtSss::setupWidget()
{
    std::cout << "*********** SetUpWidget ************" << std::endl;

    RtSssSetupWidget* widget = new RtSssSetupWidget(this);  //widget is later distroyed by CentralWidget - so it has to be created everytime new

    connect(widget, &RtSssSetupWidget::signalNewLinRR, this, &RtSss::setLinRR);
    connect(widget, &RtSssSetupWidget::signalNewLoutRR, this, &RtSss::setLoutRR);
    connect(widget, &RtSssSetupWidget::signalNewLin, this, &RtSss::setLin);
    connect(widget, &RtSssSetupWidget::signalNewLout, this, &RtSss::setLout);

    LinRR = widget->getLinRR();
    LoutRR = widget->getLoutRR();
    Lin = widget->getLin();
    Lout = widget->getLout();

    return widget;
}

void RtSss::setLinRR(int val)
{
//    std::cout <<" new LinRR: " << val << std::endl;
    LinRR = val;
}

void RtSss::setLoutRR(int val)
{
//    std::cout <<" new LoutRR: " << val << std::endl;
    LoutRR = val;
}

void RtSss::setLin(int val)
{
//    std::cout <<" new Lin: " << val << std::endl;
    Lin = val;
}

void RtSss::setLout(int val)
{
//    std::cout <<" new Lout: " << val << std::endl;
    Lout = val;
}

//*************************************************************************************************************

void RtSss::update(XMEASLIB::NewMeasurement::SPtr pMeasurement)
{
//    std::cout << "*********** Update ************" << std::endl;

    QSharedPointer<NewRealTimeMultiSampleArray> pRTMSA = pMeasurement.dynamicCast<NewRealTimeMultiSampleArray>();

    if(pRTMSA && m_bReceiveData)
    {
        //Check if buffer initialized
        if(!m_pRtSssBuffer)
            m_pRtSssBuffer = CircularMatrixBuffer<double>::SPtr(new CircularMatrixBuffer<double>(64, pRTMSA->getNumChannels(), pRTMSA->getMultiArraySize()));

        //Fiff information
        if(!m_pFiffInfo)
            m_pFiffInfo = pRTMSA->getFiffInfo();

        if(m_bProcessData)
        {
            MatrixXd in_mat(pRTMSA->getNumChannels(), pRTMSA->getMultiArraySize());
            for(unsigned char i = 0; i < pRTMSA->getMultiArraySize(); ++i)
                in_mat.col(i) = pRTMSA->getMultiSampleArray()[i];

            m_pRtSssBuffer->push(&in_mat);
        }
    }
}

//*************************************************************************************************************

void RtSss::run()
{

    RtSssAlgo rsss;
    QList<MatrixXd> lineqn, sssRR;

    m_bIsRunning = true;

    //
    // start receiving data
    //
    m_bReceiveData = true;

    // Read Fiff Info
    //
    while(!m_pFiffInfo)
        msleep(10);// Wait for fiff Info

    // Set MEG channel infomation
    rsss.setMEGInfo(m_pFiffInfo);

    // Init output
    m_pRTMSAOutput->data()->initFromFiffInfo(m_pFiffInfo);
    m_pRTMSAOutput->data()->setMultiArraySize(100);
//    m_pRTMSAOutput->data()->setSamplingRate(m_pFiffInfo->sfreq);
    m_pRTMSAOutput->data()->setVisibility(true);

    qDebug() << "LinRR (run): " << LinRR << ", LoutRR (run): " << LoutRR <<", Lin (run): " << Lin <<", Lout (run): " << Lout;
    QList<int> expOrder;
    expOrder << LinRR << LoutRR << Lin << Lout;
    rsss.setSSSParameter(expOrder);

    // Find the number of MEG channel
    qint32 nmegchan = rsss.getNumMEGCh();
//    std::cout << "number of meg channels: " << nmegchan << std::endl;

//    std::cout << "building SSS linear equation .....";
    qDebug() << "building SSS linear equation .....";
    lineqn = rsss.buildLinearEqn();
    qDebug() << " finished (run)!";

    // start processing data
    m_bProcessData = true;

    while(m_bIsRunning)
    {
        qint32 nrows = m_pRtSssBuffer->rows();

        if(nrows > 0) // check if init
        {
            // * Dispatch the inputs * //
            MatrixXd in_mat = m_pRtSssBuffer->pop();
//            std::cout << "size of in_mat (run): " << in_mat.rows() << " x " << in_mat.cols() << std::endl;

            sssRR = rsss.getSSSRR(lineqn[0], lineqn[1], lineqn[2], lineqn[3], lineqn[4]*in_mat.block(0,0,nmegchan,in_mat.cols()));
//            std::cout << "size of sssRR[0] (run): " << sssRR[0].rows() << " x " << sssRR[0].cols() << std::endl;

            for(qint32 i = 0; i <in_mat.cols(); ++i)
            {
                in_mat.block(0,i,nmegchan,1) = sssRR[0].col(i);
                m_pRTMSAOutput->data()->setValue(in_mat.col(i));
            }
        }
    }

    m_bProcessData = false;
    m_bReceiveData = false;

}

//*****************************************************************************************
//  When MEG channels don't start from the first row and may be mixed with other channels
//*****************************************************************************************
/*
for(qint32 i = 0; i <in_mat.cols(); ++i)
{
//  When MEG channels don't start from the first row and may be mixed with other channels
    qint32 m = 0;
    MatrixXd meg_mat(nmegchan, 1);
    for(qint32 j = 0; j < in_mat.rows(); ++j)
        if(m_pFiffInfo->chs[j].kind == FIFFV_MEG_CH)
        {
            meg_mat(m,0) = in_mat(j,i);
            m++;
        }

//                std::cout << "size meg_mat: " << meg_mat.rows() << " x " << meg_mat.cols() << std::endl;
      sssRR = rsss.getSSSRR(lineqn[0], lineqn[1], lineqn[2], lineqn[3], lineqn[4]*meg_mat);

    in_mat.block(0,i,nmegchan,1) = sssRR[0];
    m_pRTMSAOutput->data()->setValue(in_mat.col(i));
}
*/
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * DSP functions and operations.
 */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
#include <memory>
#include <numeric>
#include <stdint.h>
#include <vector>

#include "dsp.h"

using namespace std;

namespace radioreceiver {

const double kPi = 3.141592653989793238;
const double k2Pi = 2 * kPi;
const double kPi2 = kPi / 2;

vector<float> getLowPassFIRCoeffs(int sampleRate, float halfAmplFreq,
                                  int length) {
  length += (length + 1) % 2;
  float freq = halfAmplFreq / sampleRate;
  int center = length / 2;
  float sum = 0;
  vector<float> coefficients(length);
  for (int i = 0; i < length; ++i) {
    float val;
    if (i == center) {
      val = k2Pi * freq;
    } else {
      float angle = k2Pi * (i + 1) / (length + 1);
      val = sin(k2Pi * freq * (i - center)) / (i - center);
      val *= 0.42 - 0.5 * cos(angle) + 0.08 * cos(2 * angle);
    }
    sum += val;
    coefficients[i] = val;
  }
  for (int i = 0; i < length; ++i) {
    coefficients[i] /= sum;
  }
  return coefficients;
}

Samples samplesFromUint8(uint8_t* buffer, int length) {
  Samples out(length);
  for (int i = 0; i < length; ++i) {
    out[i] = buffer[i] / 128.0 - 1;
  }
  return out;
}

FIRFilter::FIRFilter(const vector<float>& coefficients, int step)
    : coefficients_(coefficients),
      curSamples_((coefficients.size() - 1) * step, 0),
      step_(step), offset_((coefficients.size() - 1) * step) {
  reverse(coefficients_.begin(), coefficients_.end());
}

void FIRFilter::loadSamples(const Samples& samples) {
  int fullLen = samples.size() + offset_;
  float* curArr = curSamples_.data();
  float* endOfCur = curArr + curSamples_.size() - offset_;
  memmove(curArr, endOfCur, offset_ * sizeof(float));
  if (fullLen != curSamples_.size()) {
    curSamples_.resize(fullLen);
    curArr = curSamples_.data();
  }
  memmove(curArr + offset_, samples.data(), samples.size() * sizeof(float));
}

float FIRFilter::get(int index) {
  float out = 0;
  for (int ic = 0, is = index, sz = coefficients_.size(); ic < sz;
       ++ic, is += step_) {
    out += coefficients_[ic] * curSamples_[is];
  }
  return out;
}

Downsampler::Downsampler(int inRate, int outRate,
                         const vector<float>& coefs)
    : filter_(coefs, 1), rateMul_((float) inRate / outRate) {}

Samples Downsampler::downsample(const Samples& samples) {
  filter_.loadSamples(samples);
  int outLen = samples.size() / rateMul_;
  Samples out(outLen);
  float readFrom = 0;
  for (int i = 0; i < outLen; ++i, readFrom += rateMul_) {
    out[i] = filter_.get((int) readFrom);
  }
  return out;
}

IQDownsampler::IQDownsampler(int inRate, int outRate,
                             const vector<float>& coefs)
    : filter_(coefs, 2), rateMul_((float) inRate / outRate) {}

SamplesIQ IQDownsampler::downsample(const Samples& samples) {
  int numSamples = samples.size() / (2 * rateMul_);
  filter_.loadSamples(samples);
  SamplesIQ out{Samples(numSamples), Samples(numSamples)};
  float readFrom = 0;
  for (int i = 0; i < numSamples; ++i, readFrom += rateMul_) {
    int idx = 2 * ((int) readFrom);
    out.I[i] = filter_.get(idx);
    out.Q[i] = filter_.get(idx + 1);
  }
  return out;
}

AMDemodulator::AMDemodulator(int inRate, int outRate, float filterFreq,
                             int kernelLen)
    : downsampler_(inRate, outRate,
                   getLowPassFIRCoeffs(inRate, filterFreq, kernelLen)) {}

Samples AMDemodulator::demodulateTuned(const Samples& samples) {
  SamplesIQ iqSamples(downsampler_.downsample(samples));
  int outLen = iqSamples.I.size();
  float iAvg = accumulate(iqSamples.I.begin(), iqSamples.I.end(), 0) / outLen;
  float qAvg = accumulate(iqSamples.Q.begin(), iqSamples.Q.end(), 0) / outLen;
  Samples out(outLen);
  float sigSqrSum = 0;
  float sigSum = 0;
  for (int i = 0; i < outLen; ++i) {
    float I = iqSamples.I[i] - iAvg;
    float Q = iqSamples.Q[i] - qAvg;
    float power = I * I + Q * Q;
    float ampl = sqrt(power);
    out[i] = ampl;
    sigSum += ampl;
    sigSqrSum += power;
  }
  float halfPoint = sigSum / outLen;
  for (auto &o : out) {
    o = (o - halfPoint) / halfPoint;
  }
  hasCarrier_ = sigSqrSum > (0.002 * outLen);
  return out;
}

bool AMDemodulator::hasCarrier() {
  return hasCarrier_;
}

static float myatan2(float y, float x) {
  float sgn = 1;
  if (y < 0) {
    sgn *= -1;
    y *= -1;
  }
  float ang = 0;
  float div;
  if (x == y) {
    div = 1;
  } else if (x > y) {
    div = y / x;
  } else {
    ang = -kPi2;
    div = x / y;
    sgn *= -1;
  }
  ang +=
    div /
    (0.98419158358617365
     + div * (0.093485702629671305
	      + div * 0.19556307900617517));
  return sgn * ang;
}

FMDemodulator::FMDemodulator(int inRate, int outRate, int maxF,
                             float filterFreq, int kernelLen)
  : amplConv_(outRate / (k2Pi * maxF)),
    downsampler_(inRate, outRate,
                 getLowPassFIRCoeffs(inRate, filterFreq, kernelLen)),
    lI_(0), lQ_(0) {}

Samples FMDemodulator::demodulateTuned(const Samples& samples) {
  SamplesIQ iqSamples(downsampler_.downsample(samples));
  int outLen = iqSamples.I.size();
  Samples out(outLen);
  float sigSqrSum = 0;
  for (int i = 0; i < outLen; ++i) {
    float I = iqSamples.I[i];
    float Q = iqSamples.Q[i];
    float real = lI_ * I + lQ_ * Q;
    float imag = lI_ * Q - I * lQ_;
    out[i] = myatan2(imag, real) * amplConv_;
    lI_ = I;
    lQ_ = Q;
    sigSqrSum += lI_ * lI_;
  }
  hasCarrier_ = sigSqrSum > (0.002 * outLen);
  return out;
}

bool FMDemodulator::hasCarrier() {
  return hasCarrier_;
}

class StereoSeparator::ExpAverage {
  float weight_;
  float avg_;

 public:
  ExpAverage(int weight) : weight_(weight), avg_(0) {}

  float add(float value) {
    avg_ = (weight_ * avg_ + value) / (weight_ + 1);
    return avg_;
  }

  float get() { return avg_; }
};

StereoSeparator::StereoSeparator(int sampleRate, int pilotFreq)
    : sin_(0), cos_(1),
      iavg_(new ExpAverage(sampleRate * 0.03)),
      qavg_(new ExpAverage(sampleRate * 0.03)),
      cavg_(new ExpAverage(sampleRate * 0.15)) {
  for (int i = 0; i < 8001; ++i) {
    float freq = (pilotFreq + i / 100 - 40) * k2Pi / sampleRate;
    sinTable_[i] = sin(freq);
    cosTable_[i] = cos(freq);
  }
}

StereoSeparator::~StereoSeparator() {}

const float StereoSeparator::kCorrThres = 4;

StereoSignal StereoSeparator::separate(const Samples& samples) {
  Samples out(samples);
  for (int i = 0, sz = out.size(); i < sz; ++i) {
    float hdev = qavg_->add(out[i] * cos_);
    float vdev = iavg_->add(out[i] * sin_);
    out[i] *= sin_ * cos_ * 2;
    float corr;
    if (vdev > 0) {
      corr = fmaxf(-4, fminf(4, hdev / vdev));
    } else {
      corr = hdev == 0 ? 0 : hdev > 0 ? 4 : -4;
    }
    int idx = roundf((corr + 4) * 1000);
    float newSin = sin_ * cosTable_[idx] + cos_ * sinTable_[idx];
    cos_ = cos_ * cosTable_[idx] - sin_ * sinTable_[idx];
    sin_ = newSin;
    cavg_->add(corr * corr);
  }

  return StereoSignal{cavg_->get() < kCorrThres, out};
}

Deemphasizer::Deemphasizer(int sampleRate, int timeConstant_uS)
  : mult_(exp(-1e6 / (timeConstant_uS * sampleRate))), val_(0) {}

void Deemphasizer::inPlace(Samples& samples) {
  for (int i = 0, sz = samples.size(); i < sz; ++i) {
    val_ = (1 - mult_) * samples[i] + mult_ * val_;
    samples[i] = val_;
  }
}

}  // namespace radioreceiver
<commit_msg>Fix value of π.<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * DSP functions and operations.
 */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring>
#include <memory>
#include <numeric>
#include <stdint.h>
#include <vector>

#include "dsp.h"

using namespace std;

namespace radioreceiver {

const double kPi = 3.141592653589793238;
const double k2Pi = 2 * kPi;
const double kPi2 = kPi / 2;

vector<float> getLowPassFIRCoeffs(int sampleRate, float halfAmplFreq,
                                  int length) {
  length += (length + 1) % 2;
  float freq = halfAmplFreq / sampleRate;
  int center = length / 2;
  float sum = 0;
  vector<float> coefficients(length);
  for (int i = 0; i < length; ++i) {
    float val;
    if (i == center) {
      val = k2Pi * freq;
    } else {
      float angle = k2Pi * (i + 1) / (length + 1);
      val = sin(k2Pi * freq * (i - center)) / (i - center);
      val *= 0.42 - 0.5 * cos(angle) + 0.08 * cos(2 * angle);
    }
    sum += val;
    coefficients[i] = val;
  }
  for (int i = 0; i < length; ++i) {
    coefficients[i] /= sum;
  }
  return coefficients;
}

Samples samplesFromUint8(uint8_t* buffer, int length) {
  Samples out(length);
  for (int i = 0; i < length; ++i) {
    out[i] = buffer[i] / 128.0 - 1;
  }
  return out;
}

FIRFilter::FIRFilter(const vector<float>& coefficients, int step)
    : coefficients_(coefficients),
      curSamples_((coefficients.size() - 1) * step, 0),
      step_(step), offset_((coefficients.size() - 1) * step) {
  reverse(coefficients_.begin(), coefficients_.end());
}

void FIRFilter::loadSamples(const Samples& samples) {
  int fullLen = samples.size() + offset_;
  float* curArr = curSamples_.data();
  float* endOfCur = curArr + curSamples_.size() - offset_;
  memmove(curArr, endOfCur, offset_ * sizeof(float));
  if (fullLen != curSamples_.size()) {
    curSamples_.resize(fullLen);
    curArr = curSamples_.data();
  }
  memmove(curArr + offset_, samples.data(), samples.size() * sizeof(float));
}

float FIRFilter::get(int index) {
  float out = 0;
  for (int ic = 0, is = index, sz = coefficients_.size(); ic < sz;
       ++ic, is += step_) {
    out += coefficients_[ic] * curSamples_[is];
  }
  return out;
}

Downsampler::Downsampler(int inRate, int outRate,
                         const vector<float>& coefs)
    : filter_(coefs, 1), rateMul_((float) inRate / outRate) {}

Samples Downsampler::downsample(const Samples& samples) {
  filter_.loadSamples(samples);
  int outLen = samples.size() / rateMul_;
  Samples out(outLen);
  float readFrom = 0;
  for (int i = 0; i < outLen; ++i, readFrom += rateMul_) {
    out[i] = filter_.get((int) readFrom);
  }
  return out;
}

IQDownsampler::IQDownsampler(int inRate, int outRate,
                             const vector<float>& coefs)
    : filter_(coefs, 2), rateMul_((float) inRate / outRate) {}

SamplesIQ IQDownsampler::downsample(const Samples& samples) {
  int numSamples = samples.size() / (2 * rateMul_);
  filter_.loadSamples(samples);
  SamplesIQ out{Samples(numSamples), Samples(numSamples)};
  float readFrom = 0;
  for (int i = 0; i < numSamples; ++i, readFrom += rateMul_) {
    int idx = 2 * ((int) readFrom);
    out.I[i] = filter_.get(idx);
    out.Q[i] = filter_.get(idx + 1);
  }
  return out;
}

AMDemodulator::AMDemodulator(int inRate, int outRate, float filterFreq,
                             int kernelLen)
    : downsampler_(inRate, outRate,
                   getLowPassFIRCoeffs(inRate, filterFreq, kernelLen)) {}

Samples AMDemodulator::demodulateTuned(const Samples& samples) {
  SamplesIQ iqSamples(downsampler_.downsample(samples));
  int outLen = iqSamples.I.size();
  float iAvg = accumulate(iqSamples.I.begin(), iqSamples.I.end(), 0) / outLen;
  float qAvg = accumulate(iqSamples.Q.begin(), iqSamples.Q.end(), 0) / outLen;
  Samples out(outLen);
  float sigSqrSum = 0;
  float sigSum = 0;
  for (int i = 0; i < outLen; ++i) {
    float I = iqSamples.I[i] - iAvg;
    float Q = iqSamples.Q[i] - qAvg;
    float power = I * I + Q * Q;
    float ampl = sqrt(power);
    out[i] = ampl;
    sigSum += ampl;
    sigSqrSum += power;
  }
  float halfPoint = sigSum / outLen;
  for (auto &o : out) {
    o = (o - halfPoint) / halfPoint;
  }
  hasCarrier_ = sigSqrSum > (0.002 * outLen);
  return out;
}

bool AMDemodulator::hasCarrier() {
  return hasCarrier_;
}

static float myatan2(float y, float x) {
  float sgn = 1;
  if (y < 0) {
    sgn *= -1;
    y *= -1;
  }
  float ang = 0;
  float div;
  if (x == y) {
    div = 1;
  } else if (x > y) {
    div = y / x;
  } else {
    ang = -kPi2;
    div = x / y;
    sgn *= -1;
  }
  ang +=
    div /
    (0.98419158358617365
     + div * (0.093485702629671305
	      + div * 0.19556307900617517));
  return sgn * ang;
}

FMDemodulator::FMDemodulator(int inRate, int outRate, int maxF,
                             float filterFreq, int kernelLen)
  : amplConv_(outRate / (k2Pi * maxF)),
    downsampler_(inRate, outRate,
                 getLowPassFIRCoeffs(inRate, filterFreq, kernelLen)),
    lI_(0), lQ_(0) {}

Samples FMDemodulator::demodulateTuned(const Samples& samples) {
  SamplesIQ iqSamples(downsampler_.downsample(samples));
  int outLen = iqSamples.I.size();
  Samples out(outLen);
  float sigSqrSum = 0;
  for (int i = 0; i < outLen; ++i) {
    float I = iqSamples.I[i];
    float Q = iqSamples.Q[i];
    float real = lI_ * I + lQ_ * Q;
    float imag = lI_ * Q - I * lQ_;
    out[i] = myatan2(imag, real) * amplConv_;
    lI_ = I;
    lQ_ = Q;
    sigSqrSum += lI_ * lI_;
  }
  hasCarrier_ = sigSqrSum > (0.002 * outLen);
  return out;
}

bool FMDemodulator::hasCarrier() {
  return hasCarrier_;
}

class StereoSeparator::ExpAverage {
  float weight_;
  float avg_;

 public:
  ExpAverage(int weight) : weight_(weight), avg_(0) {}

  float add(float value) {
    avg_ = (weight_ * avg_ + value) / (weight_ + 1);
    return avg_;
  }

  float get() { return avg_; }
};

StereoSeparator::StereoSeparator(int sampleRate, int pilotFreq)
    : sin_(0), cos_(1),
      iavg_(new ExpAverage(sampleRate * 0.03)),
      qavg_(new ExpAverage(sampleRate * 0.03)),
      cavg_(new ExpAverage(sampleRate * 0.15)) {
  for (int i = 0; i < 8001; ++i) {
    float freq = (pilotFreq + i / 100 - 40) * k2Pi / sampleRate;
    sinTable_[i] = sin(freq);
    cosTable_[i] = cos(freq);
  }
}

StereoSeparator::~StereoSeparator() {}

const float StereoSeparator::kCorrThres = 4;

StereoSignal StereoSeparator::separate(const Samples& samples) {
  Samples out(samples);
  for (int i = 0, sz = out.size(); i < sz; ++i) {
    float hdev = qavg_->add(out[i] * cos_);
    float vdev = iavg_->add(out[i] * sin_);
    out[i] *= sin_ * cos_ * 2;
    float corr;
    if (vdev > 0) {
      corr = fmaxf(-4, fminf(4, hdev / vdev));
    } else {
      corr = hdev == 0 ? 0 : hdev > 0 ? 4 : -4;
    }
    int idx = roundf((corr + 4) * 1000);
    float newSin = sin_ * cosTable_[idx] + cos_ * sinTable_[idx];
    cos_ = cos_ * cosTable_[idx] - sin_ * sinTable_[idx];
    sin_ = newSin;
    cavg_->add(corr * corr);
  }

  return StereoSignal{cavg_->get() < kCorrThres, out};
}

Deemphasizer::Deemphasizer(int sampleRate, int timeConstant_uS)
  : mult_(exp(-1e6 / (timeConstant_uS * sampleRate))), val_(0) {}

void Deemphasizer::inPlace(Samples& samples) {
  for (int i = 0, sz = samples.size(); i < sz; ++i) {
    val_ = (1 - mult_) * samples[i] + mult_ * val_;
    samples[i] = val_;
  }
}

}  // namespace radioreceiver
<|endoftext|>


<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2017 Roman Lebedev

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

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

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

#include "io/BitPumpJPEG.h"          // for BitPumpJPEG
#include "io/BitPumpLSB.h"           // for BitPumpLSB, BitStream<>::fillCache
#include "io/BitPumpMSB.h"           // for BitPumpMSB
#include "io/BitPumpMSB16.h"         // for BitPumpMSB16
#include "io/BitPumpMSB32.h"         // for BitPumpMSB32
#include "io/Buffer.h"               // for Buffer, Buffer::size_type, Data...
#include "io/ByteStream.h"           // for ByteStream
#include <algorithm>                 // for min
#include <benchmark/benchmark_api.h> // for State, Benchmark, Initialize
#include <cassert>                   // for assert
#include <cstddef>                   // for size_t
#include <limits>                    // for numeric_limits
#include <string>                    // for string, to_string
#include <type_traits>               // for integral_constant

using rawspeed::BitPumpLSB;
using rawspeed::BitPumpMSB;
using rawspeed::BitPumpMSB16;
using rawspeed::BitPumpMSB32;
using rawspeed::BitPumpJPEG;

static constexpr const size_t STEP_MAX = 32;

template <typename Pump>
static inline void BM_BitStream(benchmark::State& state, bool inNativeByteOrder,
                                unsigned int fillSize, unsigned int Step) {
  assert(state.range(0) > 0);
  assert((size_t)state.range(0) <=
         std::numeric_limits<rawspeed::Buffer::size_type>::max());

  assert(fillSize > 0);
  assert(fillSize <= STEP_MAX);

  assert(Step > 0);
  assert(Step <= STEP_MAX);

  assert(Step <= fillSize);

  const rawspeed::Buffer b(state.range(0));
  assert(b.getSize() > 0);
  assert(b.getSize() == (size_t)state.range(0));

  const rawspeed::DataBuffer db(b, inNativeByteOrder);
  const rawspeed::ByteStream bs(db);

  Pump pump(bs);

  size_t processedBits = 0;
  while (state.KeepRunning()) {
    pump.resetBufferPosition();

    for (processedBits = 0; processedBits <= b.getSize();) {
      pump.fill(fillSize);

      // NOTE: you may want to change the callee here
      for (auto i = 0U; i < fillSize; i += Step)
        pump.skipBits(Step);

      processedBits += fillSize;
    }
  }

  state.SetComplexityN(processedBits / 8);
  state.SetItemsProcessed(state.complexity_length_n() * state.iterations());
  state.SetBytesProcessed(state.items_processed());
}

static inline void CustomArguments(benchmark::internal::Benchmark* b) {
  b->RangeMultiplier(2);
#if 1
  b->Arg(256 << 20);
#else
  const size_t maxBytes =
      std::min(static_cast<size_t>(std::numeric_limits<int>::max()),
               static_cast<size_t>(
                   std::numeric_limits<rawspeed::Buffer::size_type>::max()));
  b->Range(1, maxBytes);
  b->Complexity(benchmark::oN);
#endif
  b->Unit(benchmark::kMillisecond);
}

using Native = std::integral_constant<bool, true>;
using NonNative = std::integral_constant<bool, false>;

template <typename BO, typename PUMP>
void registerPump(const char* byteOrder, const char* pumpName) {
  for (size_t i = 1; i <= STEP_MAX; i *= 2) {
    for (size_t j = 1; j <= i && j <= STEP_MAX; j *= 2) {
      std::string name("BM_BitStream<ByteOrder<");
      name += byteOrder;
      name += ">, Spec<";
      name += pumpName;
      name += ">, Fill<";
      name += std::to_string(i);
      name += ">, Step<";
      name += std::to_string(j);
      name += ">>";

      const auto Fn = BM_BitStream<PUMP>;
      auto* b = benchmark::RegisterBenchmark(name.c_str(), Fn, BO::value, i, j);
      b->Apply(CustomArguments);
    }
  }
}

#define REG_PUMP_2(BO, PUMP) registerPump<BO, PUMP>(#BO, #PUMP);
#define REGISTER_PUMP(PUMP) REG_PUMP_2(Native, PUMP) REG_PUMP_2(NonNative, PUMP)

int main(int argc, char** argv) {
  REGISTER_PUMP(BitPumpLSB);
  REGISTER_PUMP(BitPumpMSB);
  REGISTER_PUMP(BitPumpMSB16);
  REGISTER_PUMP(BitPumpMSB32);
  REGISTER_PUMP(BitPumpJPEG);

  benchmark::Initialize(&argc, argv);
  benchmark::RunSpecifiedBenchmarks();
}
<commit_msg>BitStreamBenchmark: fixup calculations a little<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2017 Roman Lebedev

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

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

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

#include "common/Common.h"           // for roundUp
#include "io/BitPumpJPEG.h"          // for BitPumpJPEG
#include "io/BitPumpLSB.h"           // for BitPumpLSB, BitStream<>::fillCache
#include "io/BitPumpMSB.h"           // for BitPumpMSB
#include "io/BitPumpMSB16.h"         // for BitPumpMSB16
#include "io/BitPumpMSB32.h"         // for BitPumpMSB32
#include "io/Buffer.h"               // for Buffer, Buffer::size_type, Data...
#include "io/ByteStream.h"           // for ByteStream
#include <benchmark/benchmark_api.h> // for State, Benchmark, Initialize
#include <cassert>                   // for assert
#include <cstddef>                   // for size_t
#include <limits>                    // for numeric_limits
#include <string>                    // for string, to_string
#include <type_traits>               // for integral_constant

using rawspeed::BitPumpLSB;
using rawspeed::BitPumpMSB;
using rawspeed::BitPumpMSB16;
using rawspeed::BitPumpMSB32;
using rawspeed::BitPumpJPEG;

static constexpr const size_t STEP_MAX = 32;

template <typename Pump>
static inline void BM_BitStream(benchmark::State& state, bool inNativeByteOrder,
                                unsigned int fillSize, unsigned int Step) {
  assert(state.range(0) > 0);
  assert((size_t)state.range(0) <=
         std::numeric_limits<rawspeed::Buffer::size_type>::max());

  assert(fillSize > 0);
  assert(fillSize <= STEP_MAX);

  assert(Step > 0);
  assert(Step <= STEP_MAX);

  assert(Step <= fillSize);

  assert((Step == 1) || rawspeed::isAligned(Step, 2));
  assert((fillSize == 1) || rawspeed::isAligned(fillSize, 2));

  const rawspeed::Buffer b(state.range(0));
  assert(b.getSize() > 0);
  assert(b.getSize() == (size_t)state.range(0));

  const rawspeed::DataBuffer db(b, inNativeByteOrder);
  const rawspeed::ByteStream bs(db);

  Pump pump(bs);

  size_t processedBits = 0;
  while (state.KeepRunning()) {
    pump.resetBufferPosition();

    for (processedBits = 0; processedBits <= 8 * b.getSize();) {
      pump.fill(fillSize);

      // NOTE: you may want to change the callee here
      for (auto i = 0U; i < fillSize; i += Step)
        pump.skipBitsNoFill(Step);

      processedBits += fillSize;
    }
  }

  assert(processedBits > fillSize);
  processedBits -= fillSize;

  assert(rawspeed::roundUp(8 * b.getSize(), fillSize) == processedBits);

  state.SetComplexityN(processedBits / 8);
  state.SetItemsProcessed(processedBits * state.iterations());
  state.SetBytesProcessed(state.items_processed() / 8);
}

static inline void CustomArguments(benchmark::internal::Benchmark* b) {
  b->RangeMultiplier(2);
#if 1
  b->Arg(256 << 20);
#else
  b->Range(1, 1024 << 20);
  b->Complexity(benchmark::oN);
#endif
  b->Unit(benchmark::kMillisecond);
}

using Native = std::integral_constant<bool, true>;
using NonNative = std::integral_constant<bool, false>;

template <typename BO, typename PUMP>
void registerPump(const char* byteOrder, const char* pumpName) {
  for (size_t i = 1; i <= STEP_MAX; i *= 2) {
    for (size_t j = 1; j <= i && j <= STEP_MAX; j *= 2) {
      std::string name("BM_BitStream<ByteOrder<");
      name += byteOrder;
      name += ">, Spec<";
      name += pumpName;
      name += ">, Fill<";
      name += std::to_string(i);
      name += ">, Step<";
      name += std::to_string(j);
      name += ">>";

      const auto Fn = BM_BitStream<PUMP>;
      auto* b = benchmark::RegisterBenchmark(name.c_str(), Fn, BO::value, i, j);
      b->Apply(CustomArguments);
    }
  }
}

#define REG_PUMP_2(BO, PUMP) registerPump<BO, PUMP>(#BO, #PUMP);
#define REGISTER_PUMP(PUMP) REG_PUMP_2(Native, PUMP) REG_PUMP_2(NonNative, PUMP)

int main(int argc, char** argv) {
  REGISTER_PUMP(BitPumpLSB);
  REGISTER_PUMP(BitPumpMSB);
  REGISTER_PUMP(BitPumpMSB16);
  REGISTER_PUMP(BitPumpMSB32);
  REGISTER_PUMP(BitPumpJPEG);

  benchmark::Initialize(&argc, argv);
  benchmark::RunSpecifiedBenchmarks();
}
<|endoftext|>


<commit_before>//===- StackSlots.cpp  - Specialize LLVM code for target machine ---------===//
//
// This pass adds 2 empty slots at the top of function stack.
// These two slots are later used during code reoptimization
// for spilling the resgiter values when rewriting branches.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MachineInstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"

using std::map;
using std::cerr;

class StackSlots : public FunctionPass{
private:
  const TargetMachine ⌖
public:
  StackSlots (const TargetMachine &T): target(T) {}

  bool runOnFunction(Function &F) {
    Value *v = ConstantSInt::get(Type::IntTy,0);
    MachineCodeForMethod &mcInfo = MachineCodeForMethod::get(&F);
    mcInfo.allocateLocalVar
      (target, v, 2*target.DataLayout.getTypeSize(PointerType::get(Type::IntTy)));

    return true;
  }
};

Pass* createStackSlotsPass(TargetMachine &T){
  return new StackSlots(T);
}

<commit_msg>Minor cleanups Make sure to have a pass name<commit_after>//===- StackSlots.cpp  - Specialize LLVM code for target machine ---------===//
//
// This pass adds 2 empty slots at the top of function stack.  These two slots
// are later used during code reoptimization for spilling the register values
// when rewriting branches.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/StackSlots.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MachineInstrInfo.h"
#include "llvm/Constant.h"
#include "llvm/Function.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/CodeGen/MachineCodeForMethod.h"

class StackSlots : public FunctionPass {
  const TargetMachine &Target;
public:
  StackSlots (const TargetMachine &T) : Target(T) {}

  const char *getPassName() const {
    return "Stack Slot Insertion for profiling code";
  }

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesCFG();
  }

  bool runOnFunction(Function &F) {
    const Type *PtrInt = PointerType::get(Type::IntTy);
    unsigned Size = Target.DataLayout.getTypeSize(PtrInt);

    MachineCodeForMethod &mcInfo = MachineCodeForMethod::get(&F);
    Value *V = Constant::getNullValue(Type::IntTy);
    mcInfo.allocateLocalVar(Target, V, 2*Size);
    return true;
  }
};

Pass *createStackSlotsPass(const TargetMachine &Target) {
  return new StackSlots(Target);
}
<|endoftext|>


<commit_before>//===-- X86AsmLexer.cpp - Tokenize X86 assembly to AsmTokens --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetAsmLexer.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "X86.h"

using namespace llvm;

namespace {

class X86AsmLexer : public TargetAsmLexer {
  const MCAsmInfo &AsmInfo;
protected:
  AsmToken LexToken();
public:
  X86AsmLexer(const Target &T, const MCAsmInfo &MAI)
    : TargetAsmLexer(T), AsmInfo(MAI) {
  }
};

}

AsmToken X86AsmLexer::LexToken() {
  return AsmToken(AsmToken::Error, "", 0);
}

extern "C" void LLVMInitializeX86AsmLexer() {
  RegisterAsmLexer<X86AsmLexer> X(TheX86_32Target);
  RegisterAsmLexer<X86AsmLexer> Y(TheX86_64Target);
}

//#define REGISTERS_ONLY
//#include "../X86GenAsmMatcher.inc"
//#undef REGISTERS_ONLY
<commit_msg>Implemented the dialect decision logic for the X86 TargetAsmLexer.  Dialect-specific lexing code will be placed in the functions LexTokenATT() and LexTokenIntel().<commit_after>//===-- X86AsmLexer.cpp - Tokenize X86 assembly to AsmTokens --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetAsmLexer.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "X86.h"

using namespace llvm;

namespace {

class X86AsmLexer : public TargetAsmLexer {
  const MCAsmInfo &AsmInfo;

  AsmToken LexTokenATT();
  AsmToken LexTokenIntel();
protected:
  AsmToken LexToken() {
    switch (AsmInfo.getAssemblerDialect()) {
    default:
      SetError(SMLoc(), "Unhandled dialect");
      return AsmToken(AsmToken::Error, "", 0);
    case 0:
      return LexTokenATT();
    case 1:
      return LexTokenIntel();
    }
  }
public:
  X86AsmLexer(const Target &T, const MCAsmInfo &MAI)
    : TargetAsmLexer(T), AsmInfo(MAI) {
  }
};

}

AsmToken X86AsmLexer::LexTokenATT() {
  return AsmToken(AsmToken::Error, "", 0);
}

AsmToken X86AsmLexer::LexTokenIntel() {
  return AsmToken(AsmToken::Error, "", 0);
}

extern "C" void LLVMInitializeX86AsmLexer() {
  RegisterAsmLexer<X86AsmLexer> X(TheX86_32Target);
  RegisterAsmLexer<X86AsmLexer> Y(TheX86_64Target);
}

//#define REGISTERS_ONLY
//#include "../X86GenAsmMatcher.inc"
//#undef REGISTERS_ONLY
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Monitor.h"
#include "Exception.h"
#include "Util.h"

#include <assert.h>
#include <errno.h>

#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

namespace apache { namespace thrift { namespace concurrency {

/**
 * Monitor implementation using the boost thread library
 *
 * @version $Id:$
 */
class Monitor::Impl : public boost::condition_variable {

 public:

  Impl()
     : ownedMutex_(new Mutex()),
       mutex_(NULL) {
    init(ownedMutex_.get());
  }

  Impl(Mutex* mutex)
     : mutex_(NULL) {
    init(mutex);
  }

  Impl(Monitor* monitor)
     : mutex_(NULL) {
    init(&(monitor->mutex()));
  }

  Mutex& mutex() { return *mutex_; }
  void lock() { mutex().lock(); }
  void unlock() { mutex().unlock(); }

  /**
   * Exception-throwing version of waitForTimeRelative(), called simply
   * wait(int64) for historical reasons.  Timeout is in milliseconds.
   *
   * If the condition occurs,  this function returns cleanly; on timeout or
   * error an exception is thrown.
   */
  void wait(int64_t timeout_ms) {
    int result = waitForTimeRelative(timeout_ms);
    if (result == ETIMEDOUT) {
      throw TimedOutException();
    } else if (result != 0) {
      throw TException(
        "Monitor::wait() failed");
    }
  }

  /**
   * Waits until the specified timeout in milliseconds for the condition to
   * occur, or waits forever if timeout_ms == 0.
   *
   * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code.
   */
  int waitForTimeRelative(int64_t timeout_ms) {
    if (timeout_ms == 0LL) {
      return waitForever();
    }

    assert(mutex_);
	boost::mutex* mutexImpl =
      reinterpret_cast<boost::mutex*>(mutex_->getUnderlyingImpl());
    assert(mutexImpl);

	boost::mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock);
	int res = timed_wait(lock, boost::get_system_time()+boost::posix_time::milliseconds(timeout_ms)) ? 0 : ETIMEDOUT;
	lock.release();
	return res;
  }

  /**
   * Waits until the absolute time specified using struct timespec.
   * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code.
   */
  int waitForTime(const timespec* abstime) {
    assert(mutex_);
    boost::mutex* mutexImpl =
      reinterpret_cast<boost::mutex*>(mutex_->getUnderlyingImpl());
    assert(mutexImpl);

    struct timespec currenttime;
    Util::toTimespec(currenttime, Util::currentTime());

	long tv_sec = abstime->tv_sec - currenttime.tv_sec;
	long tv_nsec = abstime->tv_nsec - currenttime.tv_nsec;
	if(tv_sec < 0)
		tv_sec = 0;
	if(tv_nsec < 0)
		tv_nsec = 0;

	boost::mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock);
	int res = timed_wait(lock, boost::get_system_time() +
		boost::posix_time::seconds(tv_sec) +
		boost::posix_time::microseconds(tv_nsec / 1000)
		) ? 0 : ETIMEDOUT;
	lock.release();
	return res;
  }

  /**
   * Waits forever until the condition occurs.
   * Returns 0 if condition occurs, or an error code otherwise.
   */
  int waitForever() {
    assert(mutex_);
    boost::mutex* mutexImpl =
      reinterpret_cast<boost::mutex*>(mutex_->getUnderlyingImpl());
    assert(mutexImpl);

	boost::mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock);
	((boost::condition_variable*)this)->wait(lock);
	lock.release();
    return 0;
  }

  void notify() {
	  notify_one();
  }

  void notifyAll() {
	  notify_all();
  }

 private:

  void init(Mutex* mutex) {
    mutex_ = mutex;
  }

  boost::scoped_ptr<Mutex> ownedMutex_;
  Mutex* mutex_;
};

Monitor::Monitor() : impl_(new Monitor::Impl()) {}
Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) {}
Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) {}

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

Mutex& Monitor::mutex() const { return const_cast<Monitor::Impl*>(impl_)->mutex(); }

void Monitor::lock() const { const_cast<Monitor::Impl*>(impl_)->lock(); }

void Monitor::unlock() const { const_cast<Monitor::Impl*>(impl_)->unlock(); }

void Monitor::wait(int64_t timeout) const { const_cast<Monitor::Impl*>(impl_)->wait(timeout); }

int Monitor::waitForTime(const timespec* abstime) const {
  return const_cast<Monitor::Impl*>(impl_)->waitForTime(abstime);
}

int Monitor::waitForTimeRelative(int64_t timeout_ms) const {
  return const_cast<Monitor::Impl*>(impl_)->waitForTimeRelative(timeout_ms);
}

int Monitor::waitForever() const {
  return const_cast<Monitor::Impl*>(impl_)->waitForever();
}

void Monitor::notify() const { const_cast<Monitor::Impl*>(impl_)->notify(); }

void Monitor::notifyAll() const { const_cast<Monitor::Impl*>(impl_)->notifyAll(); }

}}} // apache::thrift::concurrency
<commit_msg>THRIFT-1361 Optional replacement of pthread by boost::thread revert boost changes<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Monitor.h"
#include "Exception.h"
#include "Util.h"

#include <assert.h>
#include <errno.h>

#include <boost/scoped_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>

namespace apache { namespace thrift { namespace concurrency {

using namespace boost::interprocess;

/**
 * Monitor implementation using the boost interprocess library
 *
 * @version $Id:$
 */
class Monitor::Impl : public interprocess_condition {

 public:

  Impl()
     : ownedMutex_(new Mutex()),
       mutex_(NULL) {
    init(ownedMutex_.get());
  }

  Impl(Mutex* mutex)
     : mutex_(NULL) {
    init(mutex);
  }

  Impl(Monitor* monitor)
     : mutex_(NULL) {
    init(&(monitor->mutex()));
  }

  Mutex& mutex() { return *mutex_; }
  void lock() { mutex().lock(); }
  void unlock() { mutex().unlock(); }

  /**
   * Exception-throwing version of waitForTimeRelative(), called simply
   * wait(int64) for historical reasons.  Timeout is in milliseconds.
   *
   * If the condition occurs,  this function returns cleanly; on timeout or
   * error an exception is thrown.
   */
  void wait(int64_t timeout_ms) {
    int result = waitForTimeRelative(timeout_ms);
    if (result == ETIMEDOUT) {
      throw TimedOutException();
    } else if (result != 0) {
      throw TException(
        "Monitor::wait() failed");
    }
  }

  /**
   * Waits until the specified timeout in milliseconds for the condition to
   * occur, or waits forever if timeout_ms == 0.
   *
   * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code.
   */
  int waitForTimeRelative(int64_t timeout_ms) {
    if (timeout_ms == 0LL) {
      return waitForever();
    }

    assert(mutex_);
    interprocess_mutex* mutexImpl =
      reinterpret_cast<interprocess_mutex*>(mutex_->getUnderlyingImpl());
    assert(mutexImpl);

	scoped_lock<interprocess_mutex> lock(*mutexImpl, accept_ownership_type());
	int res = timed_wait(lock, boost::get_system_time()+boost::posix_time::milliseconds(timeout_ms)) ? 0 : ETIMEDOUT;
	lock.release();
	return res;
  }

  /**
   * Waits until the absolute time specified using struct timespec.
   * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code.
   */
  int waitForTime(const timespec* abstime) {
    assert(mutex_);
    interprocess_mutex* mutexImpl =
      reinterpret_cast<interprocess_mutex*>(mutex_->getUnderlyingImpl());
    assert(mutexImpl);

    struct timespec currenttime;
    Util::toTimespec(currenttime, Util::currentTime());

	long tv_sec = abstime->tv_sec - currenttime.tv_sec;
	long tv_nsec = abstime->tv_nsec - currenttime.tv_nsec;
	if(tv_sec < 0)
		tv_sec = 0;
	if(tv_nsec < 0)
		tv_nsec = 0;

	scoped_lock<interprocess_mutex> lock(*mutexImpl, accept_ownership_type());
	int res = timed_wait(lock, boost::get_system_time() +
		boost::posix_time::seconds(tv_sec) +
		boost::posix_time::microseconds(tv_nsec / 1000)
		) ? 0 : ETIMEDOUT;
	lock.release();
	return res;
  }

  /**
   * Waits forever until the condition occurs.
   * Returns 0 if condition occurs, or an error code otherwise.
   */
  int waitForever() {
    assert(mutex_);
    interprocess_mutex* mutexImpl =
      reinterpret_cast<interprocess_mutex*>(mutex_->getUnderlyingImpl());
    assert(mutexImpl);

	scoped_lock<interprocess_mutex> lock(*mutexImpl, accept_ownership_type());
	((interprocess_condition*)this)->wait(lock);
	lock.release();
    return 0;
  }

  void notify() {
	  notify_one();
  }

  void notifyAll() {
	  notify_all();
  }

 private:

  void init(Mutex* mutex) {
    mutex_ = mutex;
  }

  boost::scoped_ptr<Mutex> ownedMutex_;
  Mutex* mutex_;
};

Monitor::Monitor() : impl_(new Monitor::Impl()) {}
Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) {}
Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) {}

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

Mutex& Monitor::mutex() const { return const_cast<Monitor::Impl*>(impl_)->mutex(); }

void Monitor::lock() const { const_cast<Monitor::Impl*>(impl_)->lock(); }

void Monitor::unlock() const { const_cast<Monitor::Impl*>(impl_)->unlock(); }

void Monitor::wait(int64_t timeout) const { const_cast<Monitor::Impl*>(impl_)->wait(timeout); }

int Monitor::waitForTime(const timespec* abstime) const {
  return const_cast<Monitor::Impl*>(impl_)->waitForTime(abstime);
}

int Monitor::waitForTimeRelative(int64_t timeout_ms) const {
  return const_cast<Monitor::Impl*>(impl_)->waitForTimeRelative(timeout_ms);
}

int Monitor::waitForever() const {
  return const_cast<Monitor::Impl*>(impl_)->waitForever();
}

void Monitor::notify() const { const_cast<Monitor::Impl*>(impl_)->notify(); }

void Monitor::notifyAll() const { const_cast<Monitor::Impl*>(impl_)->notifyAll(); }

}}} // apache::thrift::concurrency
<|endoftext|>


<commit_before>// Copyright (c) 2006- Facebook
// Distributed under the Thrift Software License
//
// See accompanying file LICENSE or visit the Thrift site at:
// http://developers.facebook.com/thrift/

#include "TBinaryProtocol.h"

#include <boost/static_assert.hpp>

using std::string;

// Use this to get around strict aliasing rules.
// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
// The most obvious implementation is to just cast a pointer,
// but that doesn't work.
// For a pretty in-depth explanation of the problem, see
// http://www.cellperformance.com/mike_acton/2006/06/ (...)
// understanding_strict_aliasing.html
template <typename To, typename From>
static inline To bitwise_cast(From from) {
  BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));

  // BAD!!!  These are all broken with -O2.
  //return *reinterpret_cast<To*>(&from);  // BAD!!!
  //return *static_cast<To*>(static_cast<void*>(&from));  // BAD!!!
  //return *(To*)(void*)&from;  // BAD!!!

  // Super clean and paritally blessed by section 3.9 of the standard.
  //unsigned char c[sizeof(from)];
  //memcpy(c, &from, sizeof(from));
  //To to;
  //memcpy(&to, c, sizeof(c));
  //return to;

  // Slightly more questionable.
  // Same code emitted by GCC.
  //To to;
  //memcpy(&to, &from, sizeof(from));
  //return to;

  // Technically undefined, but almost universally supported,
  // and the most efficient implementation.
  union {
    From f;
    To t;
  } u;
  u.f = from;
  return u.t;
}

namespace facebook { namespace thrift { namespace protocol {

uint32_t TBinaryProtocol::writeMessageBegin(const std::string& name,
                                            const TMessageType messageType,
                                            const int32_t seqid) {
  if (strict_write_) {
    int32_t version = (VERSION_1) | ((int32_t)messageType);
    uint32_t wsize = 0;
    wsize += writeI32(version);
    wsize += writeString(name);
    wsize += writeI32(seqid);
    return wsize;
  } else {
    uint32_t wsize = 0;
    wsize += writeString(name);
    wsize += writeByte((int8_t)messageType);
    wsize += writeI32(seqid);
    return wsize;
  }
}

uint32_t TBinaryProtocol::writeMessageEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeStructBegin(const char* name) {
  return 0;
}

uint32_t TBinaryProtocol::writeStructEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeFieldBegin(const char* name,
                                          const TType fieldType,
                                          const int16_t fieldId) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)fieldType);
  wsize += writeI16(fieldId);
  return wsize;
}

uint32_t TBinaryProtocol::writeFieldEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeFieldStop() {
  return
    writeByte((int8_t)T_STOP);
}

uint32_t TBinaryProtocol::writeMapBegin(const TType keyType,
                                        const TType valType,
                                        const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)keyType);
  wsize += writeByte((int8_t)valType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeMapEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeListBegin(const TType elemType,
                                         const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t) elemType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeListEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeSetBegin(const TType elemType,
                                        const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)elemType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeSetEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeBool(const bool value) {
  uint8_t tmp =  value ? 1 : 0;
  trans_->write(&tmp, 1);
  return 1;
}

uint32_t TBinaryProtocol::writeByte(const int8_t byte) {
  trans_->write((uint8_t*)&byte, 1);
  return 1;
}

uint32_t TBinaryProtocol::writeI16(const int16_t i16) {
  int16_t net = (int16_t)htons(i16);
  trans_->write((uint8_t*)&net, 2);
  return 2;
}

uint32_t TBinaryProtocol::writeI32(const int32_t i32) {
  int32_t net = (int32_t)htonl(i32);
  trans_->write((uint8_t*)&net, 4);
  return 4;
}

uint32_t TBinaryProtocol::writeI64(const int64_t i64) {
  int64_t net = (int64_t)htonll(i64);
  trans_->write((uint8_t*)&net, 8);
  return 8;
}

uint32_t TBinaryProtocol::writeDouble(const double dub) {
  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);

  uint64_t bits = bitwise_cast<uint64_t>(dub);
  bits = htonll(bits);
  trans_->write((uint8_t*)&bits, 8);
  return 8;
}

uint32_t TBinaryProtocol::writeString(const string& str) {
  uint32_t size = str.size();
  uint32_t result = writeI32((int32_t)size);
  if (size > 0) {
    trans_->write((uint8_t*)str.data(), size);
  }
  return result + size;
}

uint32_t TBinaryProtocol::writeBinary(const string& str) {
  return TBinaryProtocol::writeString(str);
}

/**
 * Reading functions
 */

uint32_t TBinaryProtocol::readMessageBegin(std::string& name,
                                           TMessageType& messageType,
                                           int32_t& seqid) {
  uint32_t result = 0;
  int32_t sz;
  result += readI32(sz);

  if (sz < 0) {
    // Check for correct version number
    int32_t version = sz & VERSION_MASK;
    if (version != VERSION_1) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
    }
    messageType = (TMessageType)(sz & 0x000000ff);
    result += readString(name);
    result += readI32(seqid);
  } else {
    if (strict_read_) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
    } else {
      // Handle pre-versioned input
      int8_t type;
      result += readStringBody(name, sz);
      result += readByte(type);
      messageType = (TMessageType)type;
      result += readI32(seqid);
    }
  }
  return result;
}

uint32_t TBinaryProtocol::readMessageEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readStructBegin(string& name) {
  name = "";
  return 0;
}

uint32_t TBinaryProtocol::readStructEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readFieldBegin(string& name,
                                         TType& fieldType,
                                         int16_t& fieldId) {
  uint32_t result = 0;
  int8_t type;
  result += readByte(type);
  fieldType = (TType)type;
  if (fieldType == T_STOP) {
    fieldId = 0;
    return result;
  }
  result += readI16(fieldId);
  return result;
}

uint32_t TBinaryProtocol::readFieldEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readMapBegin(TType& keyType,
                                       TType& valType,
                                       uint32_t& size) {
  int8_t k, v;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(k);
  keyType = (TType)k;
  result += readByte(v);
  valType = (TType)v;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readMapEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readListBegin(TType& elemType,
                                        uint32_t& size) {
  int8_t e;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(e);
  elemType = (TType)e;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readListEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readSetBegin(TType& elemType,
                                       uint32_t& size) {
  int8_t e;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(e);
  elemType = (TType)e;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readSetEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readBool(bool& value) {
  uint8_t b[1];
  trans_->readAll(b, 1);
  value = *(int8_t*)b != 0;
  return 1;
}

uint32_t TBinaryProtocol::readByte(int8_t& byte) {
  uint8_t b[1];
  trans_->readAll(b, 1);
  byte = *(int8_t*)b;
  return 1;
}

uint32_t TBinaryProtocol::readI16(int16_t& i16) {
  uint8_t b[2];
  trans_->readAll(b, 2);
  i16 = *(int16_t*)b;
  i16 = (int16_t)ntohs(i16);
  return 2;
}

uint32_t TBinaryProtocol::readI32(int32_t& i32) {
  uint8_t b[4];
  trans_->readAll(b, 4);
  i32 = *(int32_t*)b;
  i32 = (int32_t)ntohl(i32);
  return 4;
}

uint32_t TBinaryProtocol::readI64(int64_t& i64) {
  uint8_t b[8];
  trans_->readAll(b, 8);
  i64 = *(int64_t*)b;
  i64 = (int64_t)ntohll(i64);
  return 8;
}

uint32_t TBinaryProtocol::readDouble(double& dub) {
  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);

  uint64_t bits;
  uint8_t b[8];
  trans_->readAll(b, 8);
  bits = *(uint64_t*)b;
  bits = ntohll(bits);
  dub = bitwise_cast<double>(bits);
  return 8;
}

uint32_t TBinaryProtocol::readString(string& str) {
  uint32_t result;
  int32_t size;
  result = readI32(size);
  return result + readStringBody(str, size);
}

uint32_t TBinaryProtocol::readBinary(string& str) {
  return TBinaryProtocol::readString(str);
}

uint32_t TBinaryProtocol::readStringBody(string& str, int32_t size) {
  uint32_t result = 0;

  // Catch error cases
  if (size < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  }
  if (string_limit_ > 0 && size > string_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }

  // Catch empty string case
  if (size == 0) {
    str = "";
    return result;
  }

  // Use the heap here to prevent stack overflow for v. large strings
  if (size > string_buf_size_ || string_buf_ == NULL) {
    void* new_string_buf = std::realloc(string_buf_, (uint32_t)size);
    if (new_string_buf == NULL) {
      throw TProtocolException(TProtocolException::UNKNOWN, "Out of memory in TBinaryProtocol::readString");
    }
    string_buf_ = (uint8_t*)new_string_buf;
    string_buf_size_ = size;
  }
  trans_->readAll(string_buf_, size);
  str = string((char*)string_buf_, size);
  return (uint32_t)size;
}

}}} // facebook::thrift::protocol
<commit_msg>Include <limits> in TBinaryProtocol.cpp for numeric_limits.<commit_after>// Copyright (c) 2006- Facebook
// Distributed under the Thrift Software License
//
// See accompanying file LICENSE or visit the Thrift site at:
// http://developers.facebook.com/thrift/

#include "TBinaryProtocol.h"

#include <limits>
#include <boost/static_assert.hpp>

using std::string;

// Use this to get around strict aliasing rules.
// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
// The most obvious implementation is to just cast a pointer,
// but that doesn't work.
// For a pretty in-depth explanation of the problem, see
// http://www.cellperformance.com/mike_acton/2006/06/ (...)
// understanding_strict_aliasing.html
template <typename To, typename From>
static inline To bitwise_cast(From from) {
  BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));

  // BAD!!!  These are all broken with -O2.
  //return *reinterpret_cast<To*>(&from);  // BAD!!!
  //return *static_cast<To*>(static_cast<void*>(&from));  // BAD!!!
  //return *(To*)(void*)&from;  // BAD!!!

  // Super clean and paritally blessed by section 3.9 of the standard.
  //unsigned char c[sizeof(from)];
  //memcpy(c, &from, sizeof(from));
  //To to;
  //memcpy(&to, c, sizeof(c));
  //return to;

  // Slightly more questionable.
  // Same code emitted by GCC.
  //To to;
  //memcpy(&to, &from, sizeof(from));
  //return to;

  // Technically undefined, but almost universally supported,
  // and the most efficient implementation.
  union {
    From f;
    To t;
  } u;
  u.f = from;
  return u.t;
}

namespace facebook { namespace thrift { namespace protocol {

uint32_t TBinaryProtocol::writeMessageBegin(const std::string& name,
                                            const TMessageType messageType,
                                            const int32_t seqid) {
  if (strict_write_) {
    int32_t version = (VERSION_1) | ((int32_t)messageType);
    uint32_t wsize = 0;
    wsize += writeI32(version);
    wsize += writeString(name);
    wsize += writeI32(seqid);
    return wsize;
  } else {
    uint32_t wsize = 0;
    wsize += writeString(name);
    wsize += writeByte((int8_t)messageType);
    wsize += writeI32(seqid);
    return wsize;
  }
}

uint32_t TBinaryProtocol::writeMessageEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeStructBegin(const char* name) {
  return 0;
}

uint32_t TBinaryProtocol::writeStructEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeFieldBegin(const char* name,
                                          const TType fieldType,
                                          const int16_t fieldId) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)fieldType);
  wsize += writeI16(fieldId);
  return wsize;
}

uint32_t TBinaryProtocol::writeFieldEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeFieldStop() {
  return
    writeByte((int8_t)T_STOP);
}

uint32_t TBinaryProtocol::writeMapBegin(const TType keyType,
                                        const TType valType,
                                        const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)keyType);
  wsize += writeByte((int8_t)valType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeMapEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeListBegin(const TType elemType,
                                         const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t) elemType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeListEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeSetBegin(const TType elemType,
                                        const uint32_t size) {
  uint32_t wsize = 0;
  wsize += writeByte((int8_t)elemType);
  wsize += writeI32((int32_t)size);
  return wsize;
}

uint32_t TBinaryProtocol::writeSetEnd() {
  return 0;
}

uint32_t TBinaryProtocol::writeBool(const bool value) {
  uint8_t tmp =  value ? 1 : 0;
  trans_->write(&tmp, 1);
  return 1;
}

uint32_t TBinaryProtocol::writeByte(const int8_t byte) {
  trans_->write((uint8_t*)&byte, 1);
  return 1;
}

uint32_t TBinaryProtocol::writeI16(const int16_t i16) {
  int16_t net = (int16_t)htons(i16);
  trans_->write((uint8_t*)&net, 2);
  return 2;
}

uint32_t TBinaryProtocol::writeI32(const int32_t i32) {
  int32_t net = (int32_t)htonl(i32);
  trans_->write((uint8_t*)&net, 4);
  return 4;
}

uint32_t TBinaryProtocol::writeI64(const int64_t i64) {
  int64_t net = (int64_t)htonll(i64);
  trans_->write((uint8_t*)&net, 8);
  return 8;
}

uint32_t TBinaryProtocol::writeDouble(const double dub) {
  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);

  uint64_t bits = bitwise_cast<uint64_t>(dub);
  bits = htonll(bits);
  trans_->write((uint8_t*)&bits, 8);
  return 8;
}

uint32_t TBinaryProtocol::writeString(const string& str) {
  uint32_t size = str.size();
  uint32_t result = writeI32((int32_t)size);
  if (size > 0) {
    trans_->write((uint8_t*)str.data(), size);
  }
  return result + size;
}

uint32_t TBinaryProtocol::writeBinary(const string& str) {
  return TBinaryProtocol::writeString(str);
}

/**
 * Reading functions
 */

uint32_t TBinaryProtocol::readMessageBegin(std::string& name,
                                           TMessageType& messageType,
                                           int32_t& seqid) {
  uint32_t result = 0;
  int32_t sz;
  result += readI32(sz);

  if (sz < 0) {
    // Check for correct version number
    int32_t version = sz & VERSION_MASK;
    if (version != VERSION_1) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
    }
    messageType = (TMessageType)(sz & 0x000000ff);
    result += readString(name);
    result += readI32(seqid);
  } else {
    if (strict_read_) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
    } else {
      // Handle pre-versioned input
      int8_t type;
      result += readStringBody(name, sz);
      result += readByte(type);
      messageType = (TMessageType)type;
      result += readI32(seqid);
    }
  }
  return result;
}

uint32_t TBinaryProtocol::readMessageEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readStructBegin(string& name) {
  name = "";
  return 0;
}

uint32_t TBinaryProtocol::readStructEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readFieldBegin(string& name,
                                         TType& fieldType,
                                         int16_t& fieldId) {
  uint32_t result = 0;
  int8_t type;
  result += readByte(type);
  fieldType = (TType)type;
  if (fieldType == T_STOP) {
    fieldId = 0;
    return result;
  }
  result += readI16(fieldId);
  return result;
}

uint32_t TBinaryProtocol::readFieldEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readMapBegin(TType& keyType,
                                       TType& valType,
                                       uint32_t& size) {
  int8_t k, v;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(k);
  keyType = (TType)k;
  result += readByte(v);
  valType = (TType)v;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readMapEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readListBegin(TType& elemType,
                                        uint32_t& size) {
  int8_t e;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(e);
  elemType = (TType)e;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readListEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readSetBegin(TType& elemType,
                                       uint32_t& size) {
  int8_t e;
  uint32_t result = 0;
  int32_t sizei;
  result += readByte(e);
  elemType = (TType)e;
  result += readI32(sizei);
  if (sizei < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  } else if (container_limit_ && sizei > container_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }
  size = (uint32_t)sizei;
  return result;
}

uint32_t TBinaryProtocol::readSetEnd() {
  return 0;
}

uint32_t TBinaryProtocol::readBool(bool& value) {
  uint8_t b[1];
  trans_->readAll(b, 1);
  value = *(int8_t*)b != 0;
  return 1;
}

uint32_t TBinaryProtocol::readByte(int8_t& byte) {
  uint8_t b[1];
  trans_->readAll(b, 1);
  byte = *(int8_t*)b;
  return 1;
}

uint32_t TBinaryProtocol::readI16(int16_t& i16) {
  uint8_t b[2];
  trans_->readAll(b, 2);
  i16 = *(int16_t*)b;
  i16 = (int16_t)ntohs(i16);
  return 2;
}

uint32_t TBinaryProtocol::readI32(int32_t& i32) {
  uint8_t b[4];
  trans_->readAll(b, 4);
  i32 = *(int32_t*)b;
  i32 = (int32_t)ntohl(i32);
  return 4;
}

uint32_t TBinaryProtocol::readI64(int64_t& i64) {
  uint8_t b[8];
  trans_->readAll(b, 8);
  i64 = *(int64_t*)b;
  i64 = (int64_t)ntohll(i64);
  return 8;
}

uint32_t TBinaryProtocol::readDouble(double& dub) {
  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);

  uint64_t bits;
  uint8_t b[8];
  trans_->readAll(b, 8);
  bits = *(uint64_t*)b;
  bits = ntohll(bits);
  dub = bitwise_cast<double>(bits);
  return 8;
}

uint32_t TBinaryProtocol::readString(string& str) {
  uint32_t result;
  int32_t size;
  result = readI32(size);
  return result + readStringBody(str, size);
}

uint32_t TBinaryProtocol::readBinary(string& str) {
  return TBinaryProtocol::readString(str);
}

uint32_t TBinaryProtocol::readStringBody(string& str, int32_t size) {
  uint32_t result = 0;

  // Catch error cases
  if (size < 0) {
    throw TProtocolException(TProtocolException::NEGATIVE_SIZE);
  }
  if (string_limit_ > 0 && size > string_limit_) {
    throw TProtocolException(TProtocolException::SIZE_LIMIT);
  }

  // Catch empty string case
  if (size == 0) {
    str = "";
    return result;
  }

  // Use the heap here to prevent stack overflow for v. large strings
  if (size > string_buf_size_ || string_buf_ == NULL) {
    void* new_string_buf = std::realloc(string_buf_, (uint32_t)size);
    if (new_string_buf == NULL) {
      throw TProtocolException(TProtocolException::UNKNOWN, "Out of memory in TBinaryProtocol::readString");
    }
    string_buf_ = (uint8_t*)new_string_buf;
    string_buf_size_ = size;
  }
  trans_->readAll(string_buf_, size);
  str = string((char*)string_buf_, size);
  return (uint32_t)size;
}

}}} // facebook::thrift::protocol
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdlib> // exit()
#include <cstdio> // printf()
#include <cstring> // memcmp()
#include <string>
#include <stack>
#include <openssl/sha.h>
#include <byteswap.h>
#include "alphabet.h"

using namespace std;

// clear text password entered by user
string pwd;

// contains the hash of the unknown password
char pwdHash[SHA256_DIGEST_LENGTH];

// contains the hash of a bruteforced string
char bruteHash[SHA256_DIGEST_LENGTH];

// the maximum number of characters bruteforce shall check
static const unsigned char MaxChars = 3;

/**
 * @brief prints 32 bytes of memory
 *
 * prints a hex dump of 32 bytes of memory pointed to
 *
 * @param[in]   pbuf: pointer to some memory, usually containing an SHA256 hash
 */
void printSHAHash(const unsigned int *const pbuf)
{
    // byteswap the integer pointed to, to display hex dump in correct order
    // TODO: how to deal with big endian machines
    printf("%X%X%X%X%X%X%X%X\n",
           bswap_32(*(pbuf)),
           bswap_32(*(pbuf+1)),
           bswap_32(*(pbuf+2)),
           bswap_32(*(pbuf+3)),
           bswap_32(*(pbuf+4)),
           bswap_32(*(pbuf+5)),
           bswap_32(*(pbuf+6)),
           bswap_32(*(pbuf+7))
          );
}

/**
 * @brief generates an SHA256 hash
 *
 * generates an SHA256 hash using openSSL
 *
 * @param[in]      input:   a const pointer to const block of data, usually a char array of which the hash is being generated
 * @param[in]      length:  the number of bytes the that input points to holds
 * @param[in,out]  hashStr: const pointer to an array of SHA256_DIGEST_LENGTH bytes that will receive the hash
 *
 * @return returns true if the hash has been generated successfully; returns false if input or hashStr is NULL or length==0; else: false
 */
bool generateSHA256(const void *const input, const size_t &length, char *const hashStr)
{
    if(!hashStr || !input || length==0)
    {
        return false;
    }

    SHA256_CTX hash;
    if(!SHA256_Init(&hash))
    {
        return false;
    }

    if(!SHA256_Update(&hash, input, length))
    {
        return false;
    }

    if(!SHA256_Final(reinterpret_cast<unsigned char*>(hashStr), &hash))
    {
        return false;
    }

    return true;
}

/**
 * @brief checks equality of two hashes
 *
 * calculates the SHA256 hash of 'password' and compares it
 * with the initial password hash
 *
 * @param[in]   password: a const string containing a guessed password
 */
void checkPassword(const string &password)
{
//#ifdef VERBOSE
    cout << "checking " << password << endl;
//#endif // VERBOSE

    // generate sha hash from entered string and write it to pwdHash
    if(!generateSHA256(password.c_str(), password.length(), bruteHash))
    {
        cerr << "Error when generating SHA256 from \"" << password << "\"" << endl;
        //return;
    }

    if (!memcmp(bruteHash, pwdHash, SHA256_DIGEST_LENGTH))
    {
        cout << "match [" << password << "]" << endl << "hash: " << endl;
        printSHAHash((unsigned int*)bruteHash);
        exit(0);
    }
}

/**
 * @brief recursive implementation of bruteforce
 *
 * recursive implementation of bruteforce attack
 * call it as follows: bruteRecursive(string(""), width);
 *
 * @param[in]   baseString: a const string indicates the prefix of a string to be checked
 * @param[in]   width:      the maximum number of characters you wish to be checked
 */
void bruteRecursive(const string baseString, const unsigned int width)
{
    for(int i=0; i<SizeAlphabet; i++)
    {
        if (baseString.length()+1 < width)
        {
            bruteRecursive(baseString+alphabet[i], width);
        }

        checkPassword(baseString+alphabet[i]);
    }
}

/**
 * @brief iterative implementation of bruteforce
 *
 * iterative implementation of bruteforce attack
 * call it as follows: bruteIterative(width);
 *
 * @param[in]   width:      the maximum number of characters you wish to be checked
 */
void bruteIterative(const unsigned int width)
{
    stack<string> myStack;

    // myStack must contain at least one element when entering loop
    // else: SIGSEGV
    // hence, start checking with an empty string
    myStack.push("");

    do
    {
        string baseString = myStack.top();
        myStack.pop();
        cout << "checking passwords with " << baseString.length()+1 << " characters..." << endl;
        for(int i=0; i<SizeAlphabet; i++)
        {
            if (baseString.length()+1 < width)
            {
                myStack.push(baseString+alphabet[i]);
            }

            checkPassword(baseString+alphabet[i]);
        }
    }
    while(!myStack.empty());
}

int main()
{
    cout << "Enter a string: " << endl;
    cin >> pwd;

    // generate sha hash from entered string and write it to pwdHash
    if(!generateSHA256(pwd.c_str(), pwd.length(), pwdHash))
    {
        cerr << "Error when generating SHA256 from \"" << pwd << "\"" << endl;
        return -2;
    }
    else
    {
        printf("SHA256 Hash for your string is:\n");
        printSHAHash((unsigned int*)pwdHash);

    }

    cout << "checking using Recusive Method" << endl;
    for(int i=1; i<=MaxChars; i++)
    {
        cout << "checking passwords with " << i << " characters..." << endl;
        bruteRecursive(string(""),i);
    }

    cout << "checking using Iterative Method" << endl;
    bruteIterative(MaxChars);

    return -1;
}
<commit_msg>do not hard exit() the prog; minor improvements<commit_after>#include <iostream>
#include <cstdio> // printf()
#include <cstring> // memcmp()
#include <string>
#include <queue>
#include <openssl/sha.h>
#include <byteswap.h>
#include "alphabet.h"

using namespace std;

// clear text password entered by user
string pwd;

// contains the hash of the unknown password
char pwdHash[SHA256_DIGEST_LENGTH];

// contains the hash of a bruteforced string
char bruteHash[SHA256_DIGEST_LENGTH];

// the maximum number of characters bruteforce shall check
static const unsigned char MaxChars = 8;

/**
 * @brief prints 32 bytes of memory
 *
 * prints a hex dump of 32 bytes of memory pointed to
 *
 * @param[in]   pbuf: pointer to some memory, usually containing an SHA256 hash
 */
void printSHAHash(const unsigned int *const pbuf)
{
    // byteswap the integer pointed to, to display hex dump in correct order
    // TODO: how to deal with big endian machines
    printf("%X%X%X%X%X%X%X%X\n",
           bswap_32(*(pbuf)),
           bswap_32(*(pbuf+1)),
           bswap_32(*(pbuf+2)),
           bswap_32(*(pbuf+3)),
           bswap_32(*(pbuf+4)),
           bswap_32(*(pbuf+5)),
           bswap_32(*(pbuf+6)),
           bswap_32(*(pbuf+7))
          );
}

/**
 * @brief generates an SHA256 hash
 *
 * generates an SHA256 hash using openSSL
 *
 * @param[in]      input:   a const pointer to const block of data, usually a char array of which the hash is being generated
 * @param[in]      length:  the number of bytes the that input points to holds
 * @param[in,out]  hashStr: const pointer to an array of SHA256_DIGEST_LENGTH bytes that will receive the hash
 *
 * @return returns true if the hash has been generated successfully; returns false if input or hashStr is NULL or length==0; else: false
 */
bool generateSHA256(const void *const input, const size_t &length, char *const hashStr)
{
    if(!hashStr || !input || length==0)
    {
        return false;
    }

    SHA256_CTX hash;
    if(!SHA256_Init(&hash))
    {
        return false;
    }

    if(!SHA256_Update(&hash, input, length))
    {
        return false;
    }

    if(!SHA256_Final(reinterpret_cast<unsigned char*>(hashStr), &hash))
    {
        return false;
    }

    return true;
}

/**
 * @brief checks equality of two hashes
 *
 * calculates the SHA256 hash of 'password' and compares it
 * with the initial password hash
 *
 * @param[in]   password: a const string containing a guessed password
 *
 * @return returns true if hashes match; false if generation of hash failed or hashes not match
 */
bool checkPassword(const string &password)
{
#ifdef VERBOSE
    cout << "checking " << password << endl;
#endif // VERBOSE

    // generate sha hash from entered string and write it to pwdHash
    if(!generateSHA256(password.c_str(), password.length(), bruteHash))
    {
        cerr << "Error when generating SHA256 from \"" << password << "\"" << endl;
        return false;
    }

    if (!memcmp(bruteHash, pwdHash, SHA256_DIGEST_LENGTH))
    {
        cout << "match [" << password << "]" << endl << "hash: " << endl;
        printSHAHash((unsigned int*)bruteHash);
        return true;
    }

    return false;
}

/**
 * @brief recursive implementation of bruteforce
 *
 * recursive implementation of bruteforce attack
 * call it as follows: bruteRecursive(string(""), width);
 *
 * @param[in]   baseString: a const string indicates the prefix of a string to be checked
 * @param[in]   width:      the maximum number of characters you wish to be checked
 */
volatile bool strFound = false;
void bruteRecursive(const string baseString, const unsigned int width)
{
    for(int i=0; (i<SizeAlphabet) && (!strFound); i++)
    {
        if (baseString.length()+1 < width)
        {
            bruteRecursive(baseString+alphabet[i], width);
        }

        if(checkPassword(baseString+alphabet[i]))
        {
            strFound = true;
        }
    }
}

/**
 * @brief iterative implementation of bruteforce
 *
 * iterative implementation of bruteforce attack
 * call it as follows: bruteIterative(width);
 *
 * @param[in]   width:      the maximum number of characters you wish to be checked
 *
 * @return return true if the password was found
 */
bool bruteIterative(const unsigned int width)
{
    queue<string> myQueue;

    // myQueue must contain at least one element when entering loop
    // else: SIGSEGV
    // hence, start checking with an empty string
    myQueue.push("");

    do
    {
        string baseString = myQueue.front();
        myQueue.pop();

        for(int i=0; i<SizeAlphabet; i++)
        {
            if (baseString.length()+1 < width)
            {
                myQueue.push(baseString+alphabet[i]);
            }

            if(checkPassword(baseString+alphabet[i]))
            {
                return true;
            }
        }
    }
    while(!myQueue.empty());
    return false;
//
//    queue<string> myQueue;
//    string baseString = "";
//    while(baseString.length() < width)
//    {
//        for(int i=0; i<SizeAlphabet; i++)
//        {
//            if (baseString.length()+1 < width)
//            {
//                myQueue.push(baseString+alphabet[i]);
//            }
//
//            if(checkPassword(baseString+alphabet[i]))
//            {
//                return true;
//            }
//        }
//
//        if(!myQueue.empty())
//        {
//            baseString = myQueue.front();
//            myQueue.pop();
//        }
//        else
//        {
//            return false;
//        }
//    }
//
//    return false;
}

int main()
{
    cout << "Enter a string: " << endl;
    cin >> pwd;

    // generate sha hash from entered string and write it to pwdHash
    if(!generateSHA256(pwd.c_str(), pwd.length(), pwdHash))
    {
        cerr << "Error when generating SHA256 from \"" << pwd << "\"" << endl;
        return -2;
    }
    else
    {
        printf("SHA256 Hash for your string is:\n");
        printSHAHash((unsigned int*)pwdHash);

    }

    cout << "checking using Recusive Method" << endl;
    for(int i=1; (i<=MaxChars) && (!strFound); i++)
    {
        cout << "checking passwords with " << i << " characters..." << endl;
        bruteRecursive(string(""),i);
    }

    cout << "checking using Iterative Method" << endl;
    bruteIterative(MaxChars);

    return 0;
}
<|endoftext|>