<commit_before>/*
 * Copyright (C) 2011 Tommi Maekitalo
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
 * NON-INFRINGEMENT.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 *
 */

#include <cxxtools/http/service.h>
#include <cxxtools/http/request.h>
#include <cxxtools/log.h>
#include "mapper.h"

log_define("cxxtools.http.mapper")

namespace cxxtools
{
namespace http
{

void Mapper::addService(const std::string& url, Service& service)
{
    log_debug("add service for url <" << url << '>');

    WriteLock serviceLock(_serviceMutex);
    _services.push_back(ServicesType::value_type(url, &service));
}

void Mapper::addService(const Regex& url, Service& service)
{
    log_debug("add service for regex");

    WriteLock serviceLock(_serviceMutex);
    _services.push_back(ServicesType::value_type(url, &service));
}

void Mapper::removeService(Service& service)
{
    WriteLock serviceLock(_serviceMutex);
    service.waitIdle();

    ServicesType::iterator it = _services.begin();
    while (it != _services.end())
    {
        if (it->second == &service)
        {
            _services.erase(it++);
        }
        else
        {
            ++it;
        }
    }
}

Responder* Mapper::getResponder(const Request& request)
{
    log_debug("get responder for url <" << request.url() << '>');

    ReadLock serviceLock(_serviceMutex);

    for (ServicesType::const_iterator it = _services.begin();
         it != _services.end(); ++it)
    {
        if (it->first.match(request.url()))
        {
            if (!it->second->checkAuth(request))
            {
                return _noAuthService.createResponder(request, it->second->realm(), it->second->authContent());
            }

            Responder* resp = it->second->doCreateResponder(request);
            if (resp)
            {
                log_debug("got responder");
                return resp;
            }
        }
    }

    log_debug("use default responder");
    return _defaultService.createResponder(request);
}

}
}
<commit_msg>fix crash in http server when last service is manually removed<commit_after>/*
 * Copyright (C) 2011 Tommi Maekitalo
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
 * NON-INFRINGEMENT.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 *
 */

#include <cxxtools/http/service.h>
#include <cxxtools/http/request.h>
#include <cxxtools/log.h>
#include "mapper.h"

log_define("cxxtools.http.mapper")

namespace cxxtools
{
namespace http
{

void Mapper::addService(const std::string& url, Service& service)
{
    log_debug("add service for url <" << url << '>');

    WriteLock serviceLock(_serviceMutex);
    _services.push_back(ServicesType::value_type(url, &service));
}

void Mapper::addService(const Regex& url, Service& service)
{
    log_debug("add service for regex");

    WriteLock serviceLock(_serviceMutex);
    _services.push_back(ServicesType::value_type(url, &service));
}

void Mapper::removeService(Service& service)
{
    WriteLock serviceLock(_serviceMutex);
    service.waitIdle();

    ServicesType::size_type n = 0;
    while (n < _services.size())
    {
        if (_services[n].second == &service)
        {
            _services.erase(_services.begin() + n);
        }
        else
        {
            ++n;
        }
    }
}

Responder* Mapper::getResponder(const Request& request)
{
    log_debug("get responder for url <" << request.url() << '>');

    ReadLock serviceLock(_serviceMutex);

    for (ServicesType::const_iterator it = _services.begin();
         it != _services.end(); ++it)
    {
        if (it->first.match(request.url()))
        {
            if (!it->second->checkAuth(request))
            {
                return _noAuthService.createResponder(request, it->second->realm(), it->second->authContent());
            }

            Responder* resp = it->second->doCreateResponder(request);
            if (resp)
            {
                log_debug("got responder");
                return resp;
            }
        }
    }

    log_debug("use default responder");
    return _defaultService.createResponder(request);
}

}
}
<|endoftext|>


<commit_before>#include "QmitkTransferFunctionGeneratorWidget.h"

#include <mitkTransferFunctionProperty.h>
#include <mitkRenderingManager.h>

#include <QFileDialog>

#include <SceneSerializationExports.h>
#include <mitkTransferFunctionPropertySerializer.h>
#include <mitkTransferFunctionPropertyDeserializer.h>

static char* presetNames[] = {  "choose an internal transferfunction preset",
                              "CT Generic",
                              "CT Black & White",
                              "CT Cardiac",
                              "CT Bone",
                              "CT Bone (with Gradient)",
                              "MR Generic" };

static int numPresetNames = sizeof( presetNames ) / sizeof( char * );

QmitkTransferFunctionGeneratorWidget::QmitkTransferFunctionGeneratorWidget(QWidget* parent,
    Qt::WindowFlags f) :
  QWidget(parent, f)
{
  histoGramm = NULL;

  this->setupUi(this);

  // LevelWindow Tab
  {
    connect( m_CrossLevelWindow, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaLevelWindow( int, int ) ) );
  }

  // Threshold Tab
  {
    connect( m_CrossThreshold, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaThreshold( int, int ) ) );
    thDelta = 100;
  }

  // Presets Tab
  {
    for(int r=0; r< numPresetNames; r++)
        m_TransferFunctionComboBox->insertItem( presetNames[r]);

    connect( m_TransferFunctionComboBox, SIGNAL( activated( int ) ), this, SLOT( OnMitkInternalPreset( int ) ) );

    connect( m_SavePreset, SIGNAL( clicked() ), this, SLOT( OnSavePreset() ) );

    connect( m_LoadPreset, SIGNAL( clicked() ), this, SLOT( OnLoadPreset() ) );
  }

  presetFileName = ".";
}

void QmitkTransferFunctionGeneratorWidget::OnSavePreset( )
{
  if(tfpToChange.IsNull())
    return;

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  std::string fileName;
  std::string fileNameOutput;

  presetFileName = QFileDialog::getSaveFileName( this,"Choose a filename to save the transferfunction",presetFileName, "Transferfunction (*.xml)" );

  fileName=presetFileName.ascii();

  LOG_INFO << "Saving Transferfunction under path: " << fileName;

  fileNameOutput= ReduceFileName(fileName);

  if ( mitk::TransferFunctionPropertySerializer::SerializeTransferFunction( fileName.c_str(),  tf ))
    m_InfoPreset->setText( QString( (std::string("saved ")+ fileNameOutput).c_str() ) );
  else
    m_InfoPreset->setText( QString( std::string("saving failed").c_str() ) );
                                           /*
  FILE *f=fopen("c:\\temp.txt","w");

  // grayvalue -> opacity
  {
    mitk::TransferFunction::ControlPoints scalarOpacityPoints = tf->GetScalarOpacityPoints();
    fprintf(f,"// grayvalue->opacity \n"
              "{\n"
              "  vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::ControlPoints::iterator iter = scalarOpacityPoints.begin(); iter != scalarOpacityPoints.end(); ++iter )
    fprintf(f,"  f->AddPoint(%f,%f);\n",iter->first, iter->second);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  // gradient
  {
    mitk::TransferFunction::ControlPoints gradientOpacityPoints = tf->GetGradientOpacityPoints();
    fprintf(f,"// gradient at grayvalue->opacity \n"
              "{\n"
              "  vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::ControlPoints::iterator iter = gradientOpacityPoints.begin(); iter != gradientOpacityPoints.end(); ++iter )
    fprintf(f,"  f->AddPoint(%f,%f);\n",iter->first, iter->second);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  // color
  {
    mitk::TransferFunction::RGBControlPoints points = tf->GetRGBPoints();

    fprintf(f,"// grayvalue->color \n"
              "{\n"
              "  vtkColorTransferFunction *f=tf->GetColorTransferFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::RGBControlPoints::iterator iter = points.begin(); iter != points.end(); ++iter )
    fprintf(f,"  f->AddRGBPoint(%f,%f,%f,%f);\n",iter->first, iter->second[0], iter->second[1], iter->second[2]);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  fclose(f);

  LOG_INFO << "saved under C:\\temp.txt";
                                             */
}

void QmitkTransferFunctionGeneratorWidget::OnLoadPreset( )
{
  if(tfpToChange.IsNull())
    return;

  std::string fileName;
  std::string fileNameOutput;

  presetFileName = QFileDialog::getOpenFileName( this,"Choose a file to open the transferfunction from",presetFileName, "Transferfunction (*.xml)"  );

  fileName=presetFileName.ascii();

  LOG_INFO << "Loading Transferfunction from path: " << fileName;

  fileNameOutput= ReduceFileName(fileName);

  mitk::TransferFunction::Pointer tf = mitk::TransferFunctionPropertyDeserializer::DeserializeTransferFunction(fileName.c_str());

  if(tf.IsNotNull())
  {
    /*
    if( histoGramm )
      tf->InitializeByItkHistogram( histoGramm );
    */

    tfpToChange->SetValue( tf );

    m_InfoPreset->setText( QString( (std::string("loaded ")+ fileNameOutput).c_str() ) );
    mitk::RenderingManager::GetInstance()->RequestUpdateAll();
    emit SignalUpdateCanvas();

    /*
    vtkFloatingPointType* dp = tf->GetScalarOpacityFunction()->GetDataPointer();
    for (int i = 0; i < tf->GetScalarOpacityFunction()->GetSize(); i++)
    {
      LOG_INFO << "x: " << dp[i * 2] << " y: " << dp[i * 2 + 1];
    }
    */
  }
}

void QmitkTransferFunctionGeneratorWidget::OnMitkInternalPreset( int mode )
{
  if(tfpToChange.IsNull())
    return;

  //first item is only information
  if( --mode == -1 )
    return;

  //revert to first item
  m_TransferFunctionComboBox->setCurrentIndex( 0 );

  // -- Creat new TransferFunction
  tfpToChange->GetValue()->SetTransferFunctionMode( mode );
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();
  m_InfoPreset->setText( QString( (std::string("selected ")+ std::string(presetNames[mode+1])).c_str() ) );
}

static double transformationGlocke ( double x )
{
  double z = 0.1;

  double a = 2 - 2 * z;

  double b = 2 * z - 1;

  x = a * x + b;

  return x;
}

static double stepFunctionGlocke ( double x )
{
  x = 1-(2*x -1.0); // map [0.5;1] to [0,1]
  x = x * ( 3*x - 2*x*x ); // apply smoothing function

  x = x * x;

  return x;
}

void QmitkTransferFunctionGeneratorWidget::OnDeltaLevelWindow(int dx, int dy)      // bell
{
  //std::string infoText;

//  m_InfoThreshold->setText( QString( x.c_str() ) );

  if(tfpToChange.IsNull())
    return;

  thPos += dx;
  thDelta -= dy;

  if(thDelta < 1)
    thDelta = 1;

  if(thDelta > 1024)
    thDelta = 1024;

  if(thPos < histoMinimum)
    thPos = histoMinimum;

  if(thPos > histoMaximum)
    thPos = histoMaximum;

  std::stringstream ss;

  ss << "Click on the cross and move the mouse"<<"\n"
     <<"\n"
     << "center at " << thPos << "\n"
     << "width " << thDelta * 2;

  m_InfoLevelWindow->setText( QString( ss.str().c_str() ) );

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  // grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();
    f->RemoveAllPoints();

    for( int r = 0; r<= 6; r++)
    {
      double relPos = (r / 6.0) * 0.5 + 0.5;
      f->AddPoint(thPos+thDelta*(-transformationGlocke(relPos)),stepFunctionGlocke(relPos));
      f->AddPoint(thPos+thDelta*( transformationGlocke(relPos)),stepFunctionGlocke(relPos));
    }

    f->Modified();
  }

  // gradient at grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();
    f->RemoveAllPoints();

    f->AddPoint( 0, 1.0 );
    f->Modified();
  }
/*
  // grayvalue->color
  {
    vtkColorTransferFunction *ctf=tf->GetColorTransferFunction();
    ctf->RemoveAllPoints();
    ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 );
    ctf->Modified();
  }
  */
  tf->Modified();

  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();
}

static double stepFunctionThreshold ( double x )
{
  x = 0.5*x + 0.5; // map [-1;1] to [0,1]
  x = x * ( 3*x - 2*x*x ); // apply smoothing function

  x = x * x;

  return x;
}

void QmitkTransferFunctionGeneratorWidget::OnDeltaThreshold(int dx, int dy)   // LEVELWINDOW
{

  if(tfpToChange.IsNull())
    return;

  thPos += dx;
  thDelta += dy;

  if(thDelta < 1)
    thDelta = 1;

  if(thDelta > 1024)
    thDelta = 1024;

  if(thPos < histoMinimum)
    thPos = histoMinimum;

  if(thPos > histoMaximum)
    thPos = histoMaximum;
          /*
  LOG_INFO << "threshold pos: " << thPos << " delta: " << thDelta;

  LOG_INFO << "histoMinimum: " << histoMinimum << " max: " << histoMaximum;
            */

  std::stringstream ss;

  ss << "Click on the cross and move the mouse"<<"\n"
     <<"\n"
     << "threshold at " << thPos << "\n"
     << "width " << thDelta * 2;

  m_InfoThreshold->setText( QString( ss.str().c_str() ) );

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  // grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();
    f->RemoveAllPoints();

    for( int r = 1; r<= 4; r++)
    {
      double relPos = r / 4.0;
      f->AddPoint(thPos+thDelta*(-relPos),stepFunctionThreshold(-relPos));
      f->AddPoint(thPos+thDelta*( relPos),stepFunctionThreshold( relPos));
    }
    f->Modified();
  }

  // gradient at grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();
    f->RemoveAllPoints();
    f->AddPoint( 0, 1.0 );
    f->Modified();
  }
/*
  // grayvalue->color
  {
    vtkColorTransferFunction *ctf=tf->GetColorTransferFunction();
    ctf->RemoveAllPoints();
    ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 );
    ctf->Modified();
  }
  */

  tf->Modified();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();

}

std::string QmitkTransferFunctionGeneratorWidget::ReduceFileName(std::string fileNameLong )
{
  if (fileNameLong.length()< 40)
    return fileNameLong;

  //LOG_INFO <<" fileName > 20 ";

  std::string fileNameShort;
  std::string fileNameRevert;

  for(int i=0; i< fileNameLong.length(); i++)
  {
    if(i<3)
    {
      char x= fileNameLong[i];
      fileNameShort= fileNameShort+x;
    }
    if(i==3)
    {
      fileNameShort= fileNameShort+"...";
      break;
    }
  }
  //LOG_INFO <<" fileNameShort: " << fileNameShort.c_str();
  for(int i=fileNameLong.length()-1; i>= 0; i--)
  {
    std::string x=std::string("")+fileNameLong[i];

    if ( x.compare("/")==0 || x.compare("\\")==0)
    {
      fileNameRevert= "/" + fileNameRevert;
      break;
    }

    if (i>=fileNameLong.length()-24)
    {
      fileNameRevert= x+ fileNameRevert;
      LOG_INFO <<" fileNameRevert: " << fileNameRevert.c_str();
    }
    else
    {
      fileNameRevert= "/..." + fileNameRevert;
      break;
    }

  }

  return fileNameShort+fileNameRevert;
}

QmitkTransferFunctionGeneratorWidget::~QmitkTransferFunctionGeneratorWidget()
{
}

void QmitkTransferFunctionGeneratorWidget::SetDataTreeNode(mitk::DataTreeNode* node)
{
  histoGramm = NULL;

  if (node)
  {
    tfpToChange = dynamic_cast<mitk::TransferFunctionProperty*>(node->GetProperty("TransferFunction"));

    if(!tfpToChange)
    {
      if (! dynamic_cast<mitk::Image*>(node->GetData()))
      {
        LOG_WARN << "QmitkTransferFunctionGeneratorWidget::SetDataTreeNode called with non-image node";
        return;
      }

      node->SetProperty("TransferFunction", tfpToChange = mitk::TransferFunctionProperty::New() );
      dynamic_cast<mitk::TransferFunctionProperty*>(node->GetProperty("TransferFunction"));
    }

    mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

    if( mitk::Image* image = dynamic_cast<mitk::Image*>( node->GetData() ) )
    {
//      tf->InitializeByItkHistogram( histoGramm = image->GetScalarHistogram() );
      histoMinimum= image->GetScalarValueMin();
      histoMaximum= image->GetScalarValueMax();
    }

    thPos = ( histoMinimum + histoMaximum ) / 2;

  }
  else
  {
    tfpToChange = 0;
    m_InfoPreset->setText( QString( "" ) );

  }
}

<commit_msg>FIX (#2733): removed debug message<commit_after>#include "QmitkTransferFunctionGeneratorWidget.h"

#include <mitkTransferFunctionProperty.h>
#include <mitkRenderingManager.h>

#include <QFileDialog>

#include <SceneSerializationExports.h>
#include <mitkTransferFunctionPropertySerializer.h>
#include <mitkTransferFunctionPropertyDeserializer.h>

static char* presetNames[] = {  "choose an internal transferfunction preset",
                              "CT Generic",
                              "CT Black & White",
                              "CT Cardiac",
                              "CT Bone",
                              "CT Bone (with Gradient)",
                              "MR Generic" };

static int numPresetNames = sizeof( presetNames ) / sizeof( char * );

QmitkTransferFunctionGeneratorWidget::QmitkTransferFunctionGeneratorWidget(QWidget* parent,
    Qt::WindowFlags f) :
  QWidget(parent, f)
{
  histoGramm = NULL;

  this->setupUi(this);

  // LevelWindow Tab
  {
    connect( m_CrossLevelWindow, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaLevelWindow( int, int ) ) );
  }

  // Threshold Tab
  {
    connect( m_CrossThreshold, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaThreshold( int, int ) ) );
    thDelta = 100;
  }

  // Presets Tab
  {
    for(int r=0; r< numPresetNames; r++)
        m_TransferFunctionComboBox->insertItem( presetNames[r]);

    connect( m_TransferFunctionComboBox, SIGNAL( activated( int ) ), this, SLOT( OnMitkInternalPreset( int ) ) );

    connect( m_SavePreset, SIGNAL( clicked() ), this, SLOT( OnSavePreset() ) );

    connect( m_LoadPreset, SIGNAL( clicked() ), this, SLOT( OnLoadPreset() ) );
  }

  presetFileName = ".";
}

void QmitkTransferFunctionGeneratorWidget::OnSavePreset( )
{
  if(tfpToChange.IsNull())
    return;

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  std::string fileName;
  std::string fileNameOutput;

  presetFileName = QFileDialog::getSaveFileName( this,"Choose a filename to save the transferfunction",presetFileName, "Transferfunction (*.xml)" );

  fileName=presetFileName.ascii();

  LOG_INFO << "Saving Transferfunction under path: " << fileName;

  fileNameOutput= ReduceFileName(fileName);

  if ( mitk::TransferFunctionPropertySerializer::SerializeTransferFunction( fileName.c_str(),  tf ))
    m_InfoPreset->setText( QString( (std::string("saved ")+ fileNameOutput).c_str() ) );
  else
    m_InfoPreset->setText( QString( std::string("saving failed").c_str() ) );
                                           /*
  FILE *f=fopen("c:\\temp.txt","w");

  // grayvalue -> opacity
  {
    mitk::TransferFunction::ControlPoints scalarOpacityPoints = tf->GetScalarOpacityPoints();
    fprintf(f,"// grayvalue->opacity \n"
              "{\n"
              "  vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::ControlPoints::iterator iter = scalarOpacityPoints.begin(); iter != scalarOpacityPoints.end(); ++iter )
    fprintf(f,"  f->AddPoint(%f,%f);\n",iter->first, iter->second);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  // gradient
  {
    mitk::TransferFunction::ControlPoints gradientOpacityPoints = tf->GetGradientOpacityPoints();
    fprintf(f,"// gradient at grayvalue->opacity \n"
              "{\n"
              "  vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::ControlPoints::iterator iter = gradientOpacityPoints.begin(); iter != gradientOpacityPoints.end(); ++iter )
    fprintf(f,"  f->AddPoint(%f,%f);\n",iter->first, iter->second);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  // color
  {
    mitk::TransferFunction::RGBControlPoints points = tf->GetRGBPoints();

    fprintf(f,"// grayvalue->color \n"
              "{\n"
              "  vtkColorTransferFunction *f=tf->GetColorTransferFunction();\n"
              "  f->RemoveAllPoints();\n");
    for ( mitk::TransferFunction::RGBControlPoints::iterator iter = points.begin(); iter != points.end(); ++iter )
    fprintf(f,"  f->AddRGBPoint(%f,%f,%f,%f);\n",iter->first, iter->second[0], iter->second[1], iter->second[2]);
    fprintf(f,"  f->Modified();\n"
              "}\n");
  }

  fclose(f);

  LOG_INFO << "saved under C:\\temp.txt";
                                             */
}

void QmitkTransferFunctionGeneratorWidget::OnLoadPreset( )
{
  if(tfpToChange.IsNull())
    return;

  std::string fileName;
  std::string fileNameOutput;

  presetFileName = QFileDialog::getOpenFileName( this,"Choose a file to open the transferfunction from",presetFileName, "Transferfunction (*.xml)"  );

  fileName=presetFileName.ascii();

  LOG_INFO << "Loading Transferfunction from path: " << fileName;

  fileNameOutput= ReduceFileName(fileName);

  mitk::TransferFunction::Pointer tf = mitk::TransferFunctionPropertyDeserializer::DeserializeTransferFunction(fileName.c_str());

  if(tf.IsNotNull())
  {
    /*
    if( histoGramm )
      tf->InitializeByItkHistogram( histoGramm );
    */

    tfpToChange->SetValue( tf );

    m_InfoPreset->setText( QString( (std::string("loaded ")+ fileNameOutput).c_str() ) );
    mitk::RenderingManager::GetInstance()->RequestUpdateAll();
    emit SignalUpdateCanvas();

    /*
    vtkFloatingPointType* dp = tf->GetScalarOpacityFunction()->GetDataPointer();
    for (int i = 0; i < tf->GetScalarOpacityFunction()->GetSize(); i++)
    {
      LOG_INFO << "x: " << dp[i * 2] << " y: " << dp[i * 2 + 1];
    }
    */
  }
}

void QmitkTransferFunctionGeneratorWidget::OnMitkInternalPreset( int mode )
{
  if(tfpToChange.IsNull())
    return;

  //first item is only information
  if( --mode == -1 )
    return;

  //revert to first item
  m_TransferFunctionComboBox->setCurrentIndex( 0 );

  // -- Creat new TransferFunction
  tfpToChange->GetValue()->SetTransferFunctionMode( mode );
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();
  m_InfoPreset->setText( QString( (std::string("selected ")+ std::string(presetNames[mode+1])).c_str() ) );
}

static double transformationGlocke ( double x )
{
  double z = 0.1;

  double a = 2 - 2 * z;

  double b = 2 * z - 1;

  x = a * x + b;

  return x;
}

static double stepFunctionGlocke ( double x )
{
  x = 1-(2*x -1.0); // map [0.5;1] to [0,1]
  x = x * ( 3*x - 2*x*x ); // apply smoothing function

  x = x * x;

  return x;
}

void QmitkTransferFunctionGeneratorWidget::OnDeltaLevelWindow(int dx, int dy)      // bell
{
  //std::string infoText;

//  m_InfoThreshold->setText( QString( x.c_str() ) );

  if(tfpToChange.IsNull())
    return;

  thPos += dx;
  thDelta -= dy;

  if(thDelta < 1)
    thDelta = 1;

  if(thDelta > 1024)
    thDelta = 1024;

  if(thPos < histoMinimum)
    thPos = histoMinimum;

  if(thPos > histoMaximum)
    thPos = histoMaximum;

  std::stringstream ss;

  ss << "Click on the cross and move the mouse"<<"\n"
     <<"\n"
     << "center at " << thPos << "\n"
     << "width " << thDelta * 2;

  m_InfoLevelWindow->setText( QString( ss.str().c_str() ) );

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  // grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();
    f->RemoveAllPoints();

    for( int r = 0; r<= 6; r++)
    {
      double relPos = (r / 6.0) * 0.5 + 0.5;
      f->AddPoint(thPos+thDelta*(-transformationGlocke(relPos)),stepFunctionGlocke(relPos));
      f->AddPoint(thPos+thDelta*( transformationGlocke(relPos)),stepFunctionGlocke(relPos));
    }

    f->Modified();
  }

  // gradient at grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();
    f->RemoveAllPoints();

    f->AddPoint( 0, 1.0 );
    f->Modified();
  }
/*
  // grayvalue->color
  {
    vtkColorTransferFunction *ctf=tf->GetColorTransferFunction();
    ctf->RemoveAllPoints();
    ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 );
    ctf->Modified();
  }
  */
  tf->Modified();

  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();
}

static double stepFunctionThreshold ( double x )
{
  x = 0.5*x + 0.5; // map [-1;1] to [0,1]
  x = x * ( 3*x - 2*x*x ); // apply smoothing function

  x = x * x;

  return x;
}

void QmitkTransferFunctionGeneratorWidget::OnDeltaThreshold(int dx, int dy)   // LEVELWINDOW
{

  if(tfpToChange.IsNull())
    return;

  thPos += dx;
  thDelta += dy;

  if(thDelta < 1)
    thDelta = 1;

  if(thDelta > 1024)
    thDelta = 1024;

  if(thPos < histoMinimum)
    thPos = histoMinimum;

  if(thPos > histoMaximum)
    thPos = histoMaximum;
          /*
  LOG_INFO << "threshold pos: " << thPos << " delta: " << thDelta;

  LOG_INFO << "histoMinimum: " << histoMinimum << " max: " << histoMaximum;
            */

  std::stringstream ss;

  ss << "Click on the cross and move the mouse"<<"\n"
     <<"\n"
     << "threshold at " << thPos << "\n"
     << "width " << thDelta * 2;

  m_InfoThreshold->setText( QString( ss.str().c_str() ) );

  mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

  // grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();
    f->RemoveAllPoints();

    for( int r = 1; r<= 4; r++)
    {
      double relPos = r / 4.0;
      f->AddPoint(thPos+thDelta*(-relPos),stepFunctionThreshold(-relPos));
      f->AddPoint(thPos+thDelta*( relPos),stepFunctionThreshold( relPos));
    }
    f->Modified();
  }

  // gradient at grayvalue->opacity
  {
    vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();
    f->RemoveAllPoints();
    f->AddPoint( 0, 1.0 );
    f->Modified();
  }
/*
  // grayvalue->color
  {
    vtkColorTransferFunction *ctf=tf->GetColorTransferFunction();
    ctf->RemoveAllPoints();
    ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 );
    ctf->Modified();
  }
  */

  tf->Modified();
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  emit SignalUpdateCanvas();

}

std::string QmitkTransferFunctionGeneratorWidget::ReduceFileName(std::string fileNameLong )
{
  if (fileNameLong.length()< 40)
    return fileNameLong;

  //LOG_INFO <<" fileName > 20 ";

  std::string fileNameShort;
  std::string fileNameRevert;

  for(int i=0; i< fileNameLong.length(); i++)
  {
    if(i<3)
    {
      char x= fileNameLong[i];
      fileNameShort= fileNameShort+x;
    }
    if(i==3)
    {
      fileNameShort= fileNameShort+"...";
      break;
    }
  }
  //LOG_INFO <<" fileNameShort: " << fileNameShort.c_str();
  for(int i=fileNameLong.length()-1; i>= 0; i--)
  {
    std::string x=std::string("")+fileNameLong[i];

    if ( x.compare("/")==0 || x.compare("\\")==0)
    {
      fileNameRevert= "/" + fileNameRevert;
      break;
    }

    if (i>=fileNameLong.length()-24)
    {
      fileNameRevert= x+ fileNameRevert;
      //LOG_INFO <<" fileNameRevert: " << fileNameRevert.c_str();
    }
    else
    {
      fileNameRevert= "/..." + fileNameRevert;
      break;
    }

  }

  return fileNameShort+fileNameRevert;
}

QmitkTransferFunctionGeneratorWidget::~QmitkTransferFunctionGeneratorWidget()
{
}

void QmitkTransferFunctionGeneratorWidget::SetDataTreeNode(mitk::DataTreeNode* node)
{
  histoGramm = NULL;

  if (node)
  {
    tfpToChange = dynamic_cast<mitk::TransferFunctionProperty*>(node->GetProperty("TransferFunction"));

    if(!tfpToChange)
    {
      if (! dynamic_cast<mitk::Image*>(node->GetData()))
      {
        LOG_WARN << "QmitkTransferFunctionGeneratorWidget::SetDataTreeNode called with non-image node";
        return;
      }

      node->SetProperty("TransferFunction", tfpToChange = mitk::TransferFunctionProperty::New() );
      dynamic_cast<mitk::TransferFunctionProperty*>(node->GetProperty("TransferFunction"));
    }

    mitk::TransferFunction::Pointer tf = tfpToChange->GetValue();

    if( mitk::Image* image = dynamic_cast<mitk::Image*>( node->GetData() ) )
    {
//      tf->InitializeByItkHistogram( histoGramm = image->GetScalarHistogram() );
      histoMinimum= image->GetScalarValueMin();
      histoMaximum= image->GetScalarValueMax();
    }

    thPos = ( histoMinimum + histoMaximum ) / 2;

  }
  else
  {
    tfpToChange = 0;
    m_InfoPreset->setText( QString( "" ) );

  }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Jeongseok Lee <jslee02@gmail.com>
 *
 * Georgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   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.
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include "dart/dynamics/EulerJoint.h"

#include <string>

#include "dart/common/Console.h"
#include "dart/math/Helpers.h"
#include "dart/math/Geometry.h"

namespace dart {
namespace dynamics {

//==============================================================================
EulerJoint::EulerJoint(const std::string& _name)
  : MultiDofJoint(_name),
    mAxisOrder(AO_XYZ)
{
  // TODO(JS): Deprecated
  mS = mJacobian;

  // TODO(JS): Deprecated
  mdS = mJacobianDeriv;
}

//==============================================================================
EulerJoint::~EulerJoint()
{
}

//==============================================================================
void EulerJoint::setAxisOrder(EulerJoint::AxisOrder _order)
{
  mAxisOrder = _order;
}

//==============================================================================
EulerJoint::AxisOrder EulerJoint::getAxisOrder() const
{
  return mAxisOrder;
}

//==============================================================================
void EulerJoint::updateLocalTransform()
{
  switch (mAxisOrder)
  {
    case AO_XYZ:
    {
      mT = mT_ParentBodyToJoint
           * Eigen::Isometry3d(math::eulerXYZToMatrix(mPositions))
           * mT_ChildBodyToJoint.inverse();
      break;
    }
    case AO_ZYX:
    {
      mT = mT_ParentBodyToJoint
           * Eigen::Isometry3d(math::eulerZYXToMatrix(mPositions))
           * mT_ChildBodyToJoint.inverse();
      break;
    }
    default:
    {
      dterr << "Undefined Euler axis order\n";
      break;
    }
  }

  assert(math::verifyTransform(mT));
}

//==============================================================================
void EulerJoint::updateLocalJacobian()
{
  double q0 = mPositions[0];
  double q1 = mPositions[1];
  double q2 = mPositions[2];

  // double c0 = cos(q0);
  double c1 = cos(q1);
  double c2 = cos(q2);

  // double s0 = sin(q0);
  double s1 = sin(q1);
  double s2 = sin(q2);

  Eigen::Vector6d J0 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J1 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J2 = Eigen::Vector6d::Zero();

  switch (mAxisOrder)
  {
    case AO_XYZ:
    {
      //------------------------------------------------------------------------
      // S = [    c1*c2, s2,  0
      //       -(c1*s2), c2,  0
      //             s1,  0,  1
      //              0,  0,  0
      //              0,  0,  0
      //              0,  0,  0 ];
      //------------------------------------------------------------------------
      J0 << c1*c2, -(c1*s2),  s1, 0.0, 0.0, 0.0;
      J1 <<    s2,       c2, 0.0, 0.0, 0.0, 0.0;
      J2 <<   0.0,      0.0, 1.0, 0.0, 0.0, 0.0;

#ifndef NDEBUG
      if (fabs(mCoordinate[1].getPos()) == DART_PI * 0.5)
        std::cout << "Singular configuration in ZYX-euler joint ["
                  << mName << "]. ("
                  << mCoordinate[0].getPos() << ", "
                  << mCoordinate[1].getPos() << ", "
                  << mCoordinate[2].getPos() << ")"
                  << std::endl;
#endif

      break;
    }
    case AO_ZYX:
    {
      //------------------------------------------------------------------------
      // S = [   -s1,    0,   1
      //       s2*c1,   c2,   0
      //       c1*c2,  -s2,   0
      //           0,    0,   0
      //           0,    0,   0
      //           0,    0,   0 ];
      //------------------------------------------------------------------------
      J0 << -s1, s2*c1, c1*c2, 0.0, 0.0, 0.0;
      J1 << 0.0,    c2,   -s2, 0.0, 0.0, 0.0;
      J2 << 1.0,   0.0,   0.0, 0.0, 0.0, 0.0;

#ifndef NDEBUG
      if (fabs(mCoordinate[1].getPos()) == DART_PI * 0.5)
        std::cout << "Singular configuration in ZYX-euler joint ["
                  << mName << "]. ("
                  << mCoordinate[0].getPos() << ", "
                  << mCoordinate[1].getPos() << ", "
                  << mCoordinate[2].getPos() << ")"
                  << std::endl;
#endif

      break;
    }
    default:
    {
      dterr << "Undefined Euler axis order\n";
      break;
    }
  }

  mJacobian.col(0) = math::AdT(mT_ChildBodyToJoint, J0);
  mJacobian.col(1) = math::AdT(mT_ChildBodyToJoint, J1);
  mJacobian.col(2) = math::AdT(mT_ChildBodyToJoint, J2);

  assert(!math::isNan(mJacobian));

#ifndef NDEBUG
  Eigen::MatrixXd JTJ = mJacobian.transpose() * mJacobian;
  Eigen::FullPivLU<Eigen::MatrixXd> luJTJ(JTJ);
  //    Eigen::FullPivLU<Eigen::MatrixXd> luS(mS);
  double det = luJTJ.determinant();
  if (det < 1e-5)
  {
    std::cout << "ill-conditioned Jacobian in joint [" << mName << "]."
              << " The determinant of the Jacobian is (" << det << ")."
              << std::endl;
    std::cout << "rank is (" << luJTJ.rank() << ")." << std::endl;
    std::cout << "det is (" << luJTJ.determinant() << ")." << std::endl;
    //        std::cout << "mS: \n" << mS << std::endl;
  }
#endif

  // TODO(JS): Deprecated
  mS = mJacobian;
}

//==============================================================================
void EulerJoint::updateLocalJacobianTimeDeriv()
{
  // double q0 = mPositions[0];
  double q1 = mPositions[1];
  double q2 = mPositions[2];

  // double dq0 = mVelocities[0];
  double dq1 = mVelocities[1];
  double dq2 = mVelocities[2];

  // double c0 = cos(q0);
  double c1 = cos(q1);
  double c2 = cos(q2);

  // double s0 = sin(q0);
  double s1 = sin(q1);
  double s2 = sin(q2);

  Eigen::Vector6d dJ0 = Eigen::Vector6d::Zero();
  Eigen::Vector6d dJ1 = Eigen::Vector6d::Zero();
  Eigen::Vector6d dJ2 = Eigen::Vector6d::Zero();

  switch (mAxisOrder)
  {
    case AO_XYZ:
    {
      //------------------------------------------------------------------------
      // dS = [  -(dq1*c2*s1) - dq2*c1*s2,    dq2*c2,  0
      //         -(dq2*c1*c2) + dq1*s1*s2, -(dq2*s2),  0
      //                           dq1*c1,         0,  0
      //                                0,         0,  0
      //                                0,         0,  0
      //                                0,         0,  0 ];
      //------------------------------------------------------------------------
      dJ0 << -(dq1*c2*s1) - dq2*c1*s2, -(dq2*c1*c2) + dq1*s1*s2, dq1*c1,
             0, 0, 0;
      dJ1 << dq2*c2,                -(dq2*s2),    0.0, 0.0, 0.0, 0.0;
      dJ2.setConstant(0.0);

      break;
    }
    case AO_ZYX:
    {
      //------------------------------------------------------------------------
      // dS = [               -c1*dq1,        0,   0
      //          c2*c1*dq2-s2*s1*dq1,  -s2*dq2,   0
      //         -s1*c2*dq1-c1*s2*dq2,  -c2*dq2,   0
      //                            0,        0,   0
      //                            0,        0,   0
      //                            0,        0,   0 ];
      //------------------------------------------------------------------------
      dJ0 << -c1*dq1, c2*c1*dq2 - s2*s1*dq1, -s1*c2*dq1 - c1*s2*dq2,
             0.0, 0.0, 0.0;
      dJ1 <<     0.0,               -s2*dq2,                -c2*dq2,
             0.0, 0.0, 0.0;
      dJ2.setConstant(0.0);
      break;
    }
    default:
    {
      dterr << "Undefined Euler axis order\n";
      break;
    }
  }

  mJacobianDeriv.col(0) = math::AdT(mT_ChildBodyToJoint, dJ0);
  mJacobianDeriv.col(1) = math::AdT(mT_ChildBodyToJoint, dJ1);
  mJacobianDeriv.col(2) = math::AdT(mT_ChildBodyToJoint, dJ2);

  assert(!math::isNan(mJacobianDeriv));

  // TODO(JS): Deprecated
  mdS = mJacobianDeriv;
}

}  // namespace dynamics
}  // namespace dart
<commit_msg>Remove use of GenCoord in debug mode<commit_after>/*
 * Copyright (c) 2013-2014, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Jeongseok Lee <jslee02@gmail.com>
 *
 * Georgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   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.
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include "dart/dynamics/EulerJoint.h"

#include <string>

#include "dart/common/Console.h"
#include "dart/math/Helpers.h"
#include "dart/math/Geometry.h"

namespace dart {
namespace dynamics {

//==============================================================================
EulerJoint::EulerJoint(const std::string& _name)
  : MultiDofJoint(_name),
    mAxisOrder(AO_XYZ)
{
  // TODO(JS): Deprecated
  mS = mJacobian;

  // TODO(JS): Deprecated
  mdS = mJacobianDeriv;
}

//==============================================================================
EulerJoint::~EulerJoint()
{
}

//==============================================================================
void EulerJoint::setAxisOrder(EulerJoint::AxisOrder _order)
{
  mAxisOrder = _order;
}

//==============================================================================
EulerJoint::AxisOrder EulerJoint::getAxisOrder() const
{
  return mAxisOrder;
}

//==============================================================================
void EulerJoint::updateLocalTransform()
{
  switch (mAxisOrder)
  {
    case AO_XYZ:
    {
      mT = mT_ParentBodyToJoint
           * Eigen::Isometry3d(math::eulerXYZToMatrix(mPositions))
           * mT_ChildBodyToJoint.inverse();
      break;
    }
    case AO_ZYX:
    {
      mT = mT_ParentBodyToJoint
           * Eigen::Isometry3d(math::eulerZYXToMatrix(mPositions))
           * mT_ChildBodyToJoint.inverse();
      break;
    }
    default:
    {
      dterr << "Undefined Euler axis order\n";
      break;
    }
  }

  assert(math::verifyTransform(mT));
}

//==============================================================================
void EulerJoint::updateLocalJacobian()
{
  double q0 = mPositions[0];
  double q1 = mPositions[1];
  double q2 = mPositions[2];

  // double c0 = cos(q0);
  double c1 = cos(q1);
  double c2 = cos(q2);

  // double s0 = sin(q0);
  double s1 = sin(q1);
  double s2 = sin(q2);

  Eigen::Vector6d J0 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J1 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J2 = Eigen::Vector6d::Zero();

  switch (mAxisOrder)
  {
    case AO_XYZ:
    {
      //------------------------------------------------------------------------
      // S = [    c1*c2, s2,  0
      //       -(c1*s2), c2,  0
      //             s1,  0,  1
      //              0,  0,  0
      //              0,  0,  0
      //              0,  0,  0 ];
      //------------------------------------------------------------------------
      J0 << c1*c2, -(c1*s2),  s1, 0.0, 0.0, 0.0;
      J1 <<    s2,       c2, 0.0, 0.0, 0.0, 0.0;
      J2 <<   0.0,      0.0, 1.0, 0.0, 0.0, 0.0;

#ifndef NDEBUG
      if (fabs(mPositions[1]) == DART_PI * 0.5)
        std::cout << "Singular configuration in ZYX-euler joint ["
                  << mName << "]. ("
                  << mPositions[0] << ", "
                  << mPositions[1] << ", "
                  << mPositions[2] << ")"
                  << std::endl;
#endif

      break;
    }
    case AO_ZYX:
    {
      //------------------------------------------------------------------------
      // S = [   -s1,    0,   1
      //       s2*c1,   c2,   0
      //       c1*c2,  -s2,   0
      //           0,    0,   0
      //           0,    0,   0
      //           0,    0,   0 ];
      //------------------------------------------------------------------------
      J0 << -s1, s2*c1, c1*c2, 0.0, 0.0, 0.0;
      J1 << 0.0,    c2,   -s2, 0.0, 0.0, 0.0;
      J2 << 1.0,   0.0,   0.0, 0.0, 0.0, 0.0;

#ifndef NDEBUG
      if (fabs(mPositions[1]) == DART_PI * 0.5)
        std::cout << "Singular configuration in ZYX-euler joint ["
                  << mName << "]. ("
                  << mPositions[0] << ", "
                  << mPositions[1] << ", "
                  << mPositions[2] << ")"
                  << std::endl;
#endif

      break;
    }
    default:
    {
      dterr << "Undefined Euler axis order\n";
      break;
    }
  }

  mJacobian.col(0) = math::AdT(mT_ChildBodyToJoint, J0);
  mJacobian.col(1) = math::AdT(mT_ChildBodyToJoint, J1);
  mJacobian.col(2) = math::AdT(mT_ChildBodyToJoint, J2);

  assert(!math::isNan(mJacobian));

#ifndef NDEBUG
  Eigen::MatrixXd JTJ = mJacobian.transpose() * mJacobian;
  Eigen::FullPivLU<Eigen::MatrixXd> luJTJ(JTJ);
  //    Eigen::FullPivLU<Eigen::MatrixXd> luS(mS);
  double det = luJTJ.determinant();
  if (det < 1e-5)
  {
    std::cout << "ill-conditioned Jacobian in joint [" << mName << "]."
              << " The determinant of the Jacobian is (" << det << ")."
              << std::endl;
    std::cout << "rank is (" << luJTJ.rank() << ")." << std::endl;
    std::cout << "det is (" << luJTJ.determinant() << ")." << std::endl;
    //        std::cout << "mS: \n" << mS << std::endl;
  }
#endif

  // TODO(JS): Deprecated
  mS = mJacobian;
}

//==============================================================================
void EulerJoint::updateLocalJacobianTimeDeriv()
{
  // double q0 = mPositions[0];
  double q1 = mPositions[1];
  double q2 = mPositions[2];

  // double dq0 = mVelocities[0];
  double dq1 = mVelocities[1];
  double dq2 = mVelocities[2];

  // double c0 = cos(q0);
  double c1 = cos(q1);
  double c2 = cos(q2);

  // double s0 = sin(q0);
  double s1 = sin(q1);
  double s2 = sin(q2);

  Eigen::Vector6d dJ0 = Eigen::Vector6d::Zero();
  Eigen::Vector6d dJ1 = Eigen::Vector6d::Zero();
  Eigen::Vector6d dJ2 = Eigen::Vector6d::Zero();

  switch (mAxisOrder)
  {
    case AO_XYZ:
    {
      //------------------------------------------------------------------------
      // dS = [  -(dq1*c2*s1) - dq2*c1*s2,    dq2*c2,  0
      //         -(dq2*c1*c2) + dq1*s1*s2, -(dq2*s2),  0
      //                           dq1*c1,         0,  0
      //                                0,         0,  0
      //                                0,         0,  0
      //                                0,         0,  0 ];
      //------------------------------------------------------------------------
      dJ0 << -(dq1*c2*s1) - dq2*c1*s2, -(dq2*c1*c2) + dq1*s1*s2, dq1*c1,
             0, 0, 0;
      dJ1 << dq2*c2,                -(dq2*s2),    0.0, 0.0, 0.0, 0.0;
      dJ2.setConstant(0.0);

      break;
    }
    case AO_ZYX:
    {
      //------------------------------------------------------------------------
      // dS = [               -c1*dq1,        0,   0
      //          c2*c1*dq2-s2*s1*dq1,  -s2*dq2,   0
      //         -s1*c2*dq1-c1*s2*dq2,  -c2*dq2,   0
      //                            0,        0,   0
      //                            0,        0,   0
      //                            0,        0,   0 ];
      //------------------------------------------------------------------------
      dJ0 << -c1*dq1, c2*c1*dq2 - s2*s1*dq1, -s1*c2*dq1 - c1*s2*dq2,
             0.0, 0.0, 0.0;
      dJ1 <<     0.0,               -s2*dq2,                -c2*dq2,
             0.0, 0.0, 0.0;
      dJ2.setConstant(0.0);
      break;
    }
    default:
    {
      dterr << "Undefined Euler axis order\n";
      break;
    }
  }

  mJacobianDeriv.col(0) = math::AdT(mT_ChildBodyToJoint, dJ0);
  mJacobianDeriv.col(1) = math::AdT(mT_ChildBodyToJoint, dJ1);
  mJacobianDeriv.col(2) = math::AdT(mT_ChildBodyToJoint, dJ2);

  assert(!math::isNan(mJacobianDeriv));

  // TODO(JS): Deprecated
  mdS = mJacobianDeriv;
}

}  // namespace dynamics
}  // namespace dart
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <string>
#include <string.h>
#include <csignal>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <functional>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <sstream>

#include <cassert>
#include <vector>
#include <fstream>
#include <future>

#include <ctime>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino {

	class Request;
	class Response;

	struct {

		time_t time;
   		struct tm *t_st;

		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::unordered_map<std::string,
			std::function<Response(std::shared_ptr<Request>)>
		> routes;

	} context;

	namespace Log{

		std::string current(){
			char timestr[256];
   			time(&context.time);
			strftime(timestr, 255, "%Y-%m-%d %H:%M:%S %Z", localtime(&context.time));
			return timestr;
		}

		static int LogLevel = 0;
		static void debug(std::string msg){
			if(LogLevel >= 1){
				std::cout <<current()<<"[debug] "<< msg << std::endl;
			}
		}

		static void info(std::string msg){
			if(LogLevel >= 2){
				std::cout <<current()<<"[info] "<< msg << std::endl;
			}
		}
	};

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;

	pair<string,string> openFile(string aFilename){
		auto filename = aFilename;
		std::ifstream ifs( filename, std::ios::in | std::ios::binary);
		if(ifs.fail()){
			throw std::runtime_error("No such file or directory \""+ filename +"\"\n");
		}
		ifs.seekg( 0, std::ios::end);
		auto pos = ifs.tellg();
		ifs.seekg( 0, std::ios::beg);

		std::vector<char> buf(pos);
		ifs.read(buf.data(), pos);
		string response(buf.cbegin(), buf.cend());

		if( response[0] == '\xFF' && response[1] == '\xD8'){
			return make_pair(response, "image/jpg");
		}else if( response[0] == '\x89' && response[1] == 'P' && response[2] == 'N' && response[3] == 'G'){
			return make_pair(response, "image/png");
		}else if( response[0] == 'G' && response[1] == 'I' && response[2] == 'F' && response[3] == '8' && (response[4] == '7' || response[4] == '9') && response[2] == 'a'){
			return make_pair(response, "image/gif");
		}else{
			return make_pair(response, "text/html");
		}
	}

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dvp:")) != -1){
			switch(result){
			case 'd':
				Log::LogLevel = 1;
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			case 'v':
				Log::info("version 0.0.3");
				exit(0);
			}
		}
	}

	class Request{
		map<string, string> headerset;
		map<string, string> paramset;
		bool correctRequest;
	  public:
		Request(string method, string url,string protocol):
		method(move(method)),
		url(move(url)),
		protocol(move(protocol))
		{
			correctRequest = validateHttpVersion(protocol);
		}

		const string method;
		const string url;
		const string protocol;

		//  HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
		bool validateHttpVersion(string v){
			if(v.size() < 5) return false;
			if(v[0] != 'H' || v[1] != 'T' ||
				v[2] != 'T' || v[3] != 'P') return false;

			if(v[4] != '/') return false;
			for(int i=5;i < v.size();i++){
				if(!isdigit(v[i]) && v[i] != '.') return false;
			}
			return true;
		}
		void addHeader(string key,string value){
			headerset[key] = move(value);
		}

		void addParams(string key,string value){
			paramset[key] = move(value);
		}

		string header(string key){
			if(headerset.find(key) == headerset.end())
				return "INVALID";
			return headerset[key];
		}

		string params(string key){
			if(paramset.find(key) == paramset.end())
				return "INVALID";
			return paramset[key];
		}
	};

    class Response{

		unordered_map<string, string> headerset;

		int status_;
		string message_;
		string url_;
		string body_;
		string protocol_;
      public:

		Response(weak_ptr<Request> req){
			auto r = req.lock();
			if(r){
				url_ = r->url;
				protocol_ = r->protocol;
			}else{
				throw std::runtime_error("Request  expired!\n");
			}
		}

		Response(int st,string msg,string pro, string bod):
			status_(st),
			message_(msg),
			body(bod),
			protocol(pro)
		{}

		Response* message(string msg){
			message_ = msg;
			return this;
		}

		Response* status(int st){
			status_ = st;
			return this;
		}

		Response* headeer(string key,string val){
			if(headerset.find(key)!= headerset.end())
				Log::debug(key+" is already setted.");
			headerset[key] = val;
			return this;
		}

		Response* file(string filename){
			auto file = openFile(*context.view_root + "/" + filename);
			body_ = file.first;
			headerset["Content-type"] = move(file.second);
			return this;
		}

      	operator string(){
      		return protocol_ + " " + to_string(status_) +" "+ message_ + "\n\n" + body_;
      	}
    };

	string createResponse(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request", "HTTP/1.1", "NN");

		auto tops = utils::split(lines[0], " ");
		if(tops.size() < 3)
			return Response(401, "Bad Request", "HTTP/1.1",  "NN");

		Log::debug(tops[0] +" "+ tops[1] +" "+ tops[2]);

		auto request = shared_ptr<Request>(new Request(tops[0],tops[1],tops[2]));

		if(context.routes.find(tops[1]) != context.routes.end()){
			return context.routes[tops[1]](move(request));
		}

		return Response( 404,"Not found", tops[2], "AA");
	}

	string receiveProcess(int sessionfd){
		char buf[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return createResponse(buf);
	}

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename != "")
			directory += "/" + move(filename);
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
			if(dir!=NULL){
		    	closedir(dir);
			}
		}else{
			Log::debug("add "+directory);
			context.routes.insert( make_pair(
				"/" + directory,
				[directory,filename](std::shared_ptr<Request> request) -> Cappuccino::Response{
					return Response(200,"OK","HTTP/1.1",openFile(directory).first);
				}
			));
		}
	}

	void loadStaticFiles() noexcept{
		load(*context.static_root,"");
	}

	void route(string url,std::function<Response(std::shared_ptr<Request>)> F){
		context.routes.insert( make_pair( move(url), move(F) ));
	}

	void root(string r){
		context.view_root =  make_shared<string>(move(r));
	}

	void resource(string s){
		context.static_root = make_shared<string>(move(s));
	}

	void run(){

		init_socket();
		signal_utils::init_signal();
		loadStaticFiles();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

	    while(1) {

	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
			for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
						int clientfd = accept(context.sockfd,
							(struct sockaddr *)&client,(socklen_t *) &len);
						FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receiveProcess(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;
	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");
	}
};

namespace Cocoa{
	using namespace Cappuccino;
	using namespace std;

	// Unit Test
	void testOpenFile(){
		auto res = openFile("html/index.html");
		auto lines = utils::split(res.first, "\n");
		assert(!lines.empty());
	}

	void testOpenInvalidFile(){
		try{
			auto res = openFile("html/index");
		}catch(std::runtime_error e){
			cout<< e.what() << endl;
		}
	}
};

<commit_msg>[Add] Validate<commit_after>#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <string>
#include <string.h>
#include <csignal>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <functional>
#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <sstream>

#include <cassert>
#include <vector>
#include <fstream>
#include <future>

#include <ctime>

#define BUF_SIZE 4096
#define MAX_LISTEN 128

namespace Cappuccino {

	class Request;
	class Response;

	struct {

		time_t time;
   	struct tm *t_st;

		int port = 1204;
		int sockfd = 0;
		int sessionfd = 0;
	    fd_set mask1fds, mask2fds;

		std::shared_ptr<std::string> view_root;
		std::shared_ptr<std::string> static_root;

		std::unordered_map<std::string,
			std::function<Response(std::shared_ptr<Request>)>
		> routes;

	} context;

	namespace Log{

		std::string current(){
			char timestr[256];
   			time(&context.time);
			strftime(timestr, 255, "%Y-%m-%d %H:%M:%S %Z", localtime(&context.time));
			return timestr;
		}

		static int LogLevel = 0;
		static void debug(std::string msg){
			if(LogLevel >= 1){
				std::cout <<current()<<"[debug] "<< msg << std::endl;
			}
		}

		static void info(std::string msg){
			if(LogLevel >= 2){
				std::cout <<current()<<"[info] "<< msg << std::endl;
			}
		}
	};

	namespace signal_utils{

		void signal_handler(int signal){
			close(context.sessionfd);
			close(context.sockfd);
			exit(0);
		}

		void signal_handler_child(int SignalName){
			while(waitpid(-1,NULL,WNOHANG)>0){}
	        signal(SIGCHLD, signal_utils::signal_handler_child);
		}

		void init_signal(){
			if(signal(SIGINT, signal_utils::signal_handler) == SIG_ERR){
				exit(1);
			}
			if(signal(SIGCHLD, signal_utils::signal_handler_child) == SIG_ERR){
				exit(1);
			}
		}
	}

	namespace utils{
		std::vector<std::string> split(const std::string& str, std::string delim) noexcept{
			std::vector<std::string> result;
		    std::string::size_type pos = 0;
		    while(pos != std::string::npos ){
		        std::string::size_type p = str.find(delim, pos);
		        if(p == std::string::npos){
		            result.push_back(str.substr(pos));
		            break;
		        }else{
		            result.push_back(str.substr(pos, p - pos));
		        }
		        pos = p + delim.size();
		    }
		    return result;
		}
	};

	void init_socket(){
	    struct sockaddr_in server;
		if((context.sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
			exit(EXIT_FAILURE);
		}
		memset( &server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(context.port);

		char opt = 1;
		setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(char));

		int temp = 1;
  		if(setsockopt(context.sockfd, SOL_SOCKET, SO_REUSEADDR,
	        &temp, sizeof(int))){
		}

		if (bind(context.sockfd, (struct sockaddr *) &server, sizeof(server)) < 0) {
			exit(EXIT_FAILURE);
		}

		if(listen(context.sockfd,  MAX_LISTEN) < 0) {
			exit(EXIT_FAILURE);
		}

	    FD_ZERO(&context.mask1fds);
	    FD_SET(context.sockfd, &context.mask1fds);
	}

	using namespace std;

	pair<string,string> openFile(string aFilename){
		auto filename = aFilename;
		std::ifstream ifs( filename, std::ios::in | std::ios::binary);
		if(ifs.fail()){
			throw std::runtime_error("No such file or directory \""+ filename +"\"\n");
		}
		ifs.seekg( 0, std::ios::end);
		auto pos = ifs.tellg();
		ifs.seekg( 0, std::ios::beg);

		std::vector<char> buf(pos);
		ifs.read(buf.data(), pos);
		string response(buf.cbegin(), buf.cend());

		if( response[0] == '\xFF' && response[1] == '\xD8'){
			return make_pair(response, "image/jpg");
		}else if( response[0] == '\x89' && response[1] == 'P' && response[2] == 'N' && response[3] == 'G'){
			return make_pair(response, "image/png");
		}else if( response[0] == 'G' && response[1] == 'I' && response[2] == 'F' && response[3] == '8' && (response[4] == '7' || response[4] == '9') && response[2] == 'a'){
			return make_pair(response, "image/gif");
		}else{
			return make_pair(response, "text/html");
		}
	}

	void option(int argc, char *argv[]) noexcept{
		char result;
		while((result = getopt(argc,argv,"dvp:")) != -1){
			switch(result){
			case 'd':
				Log::LogLevel = 1;
				break;
			case 'p':
				context.port = atoi(optarg);
				break;
			case 'v':
				Log::info("version 0.0.3");
				exit(0);
			}
		}
	}

	class Request{
		map<string, string> headerset;
		map<string, string> paramset;
		bool correctRequest;
	  public:
		Request(string method, string url,string protocol):
		method(move(method)),
		url(move(url)),
		protocol(move(protocol))
		{
			correctRequest = validateHttpVersion(protocol);
		}

		const string method;
		const string url;
		const string protocol;

		//  HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
		bool validateHttpVersion(string v){
			if(v.size() < 5) return false;
			if(v[0] != 'H' || v[1] != 'T' ||
				v[2] != 'T' || v[3] != 'P') return false;

			if(v[4] != '/') return false;
			for(int i=5;i < v.size();i++){
				if(!isdigit(v[i]) && v[i] != '.') return false;
			}
			return true;
		}
		void addHeader(string key,string value){
			headerset[key] = move(value);
		}

		void addParams(string key,string value){
			paramset[key] = move(value);
		}

		string header(string key){
			if(headerset.find(key) == headerset.end())
				return "INVALID";
			return headerset[key];
		}

		string params(string key){
			if(paramset.find(key) == paramset.end())
				return "INVALID";
			return paramset[key];
		}

		bool isCorrect(){
			return correctRequest;
		}
	};

    class Response{

		unordered_map<string, string> headerset;

		int status_;
		string message_;
		string url_;
		string body_;
		string protocol_;
      public:

		Response(weak_ptr<Request> req){
			auto r = req.lock();
			if(r){
				url_ = r->url;
				protocol_ = r->protocol;
			}else{
				throw std::runtime_error("Request  expired!\n");
			}
		}

		Response(int st,string msg,string pro, string bod):
			status_(st),
			message_(msg),
			body(bod),
			protocol(pro)
		{}

		Response* message(string msg){
			message_ = msg;
			return this;
		}

		Response* status(int st){
			status_ = st;
			return this;
		}

		Response* headeer(string key,string val){
			if(headerset.find(key)!= headerset.end())
				Log::debug(key+" is already setted.");
			headerset[key] = val;
			return this;
		}

		Response* file(string filename){
			auto file = openFile(*context.view_root + "/" + filename);
			body_ = file.first;
			headerset["Content-type"] = move(file.second);
			return this;
		}

      	operator string(){
      		return protocol_ + " " + to_string(status_) +" "+ message_ + "\n\n" + body_;
      	}
    };

	string createResponse(char* req) noexcept{
		auto lines = utils::split(string(req), "\n");
		if(lines.empty())
			return Response(400, "Bad Request", "HTTP/1.1", "NN");

		auto tops = utils::split(lines[0], " ");
		if(tops.size() < 3)
			return Response(401, "Bad Request", "HTTP/1.1",  "NN");

		Log::debug(tops[0] +" "+ tops[1] +" "+ tops[2]);

		auto request = shared_ptr<Request>(new Request(tops[0],tops[1],tops[2]));

		if(!request.isCorrect()){
			return Response( 401,"Bad Request", tops[2], "AA");
		}

		if(context.routes.find(tops[1]) != context.routes.end()){
			return context.routes[tops[1]](move(request));
		}

		return Response( 404,"Not found", tops[2], "AA");
	}

	string receiveProcess(int sessionfd){
		char buf[BUF_SIZE] = {};

		if (recv(sessionfd, buf, sizeof(buf), 0) < 0) {
			exit(EXIT_FAILURE);
		}
		do{
			if(strstr(buf, "\r\n")){
				break;
			}
			if (strlen(buf) >= sizeof(buf)) {
				memset(&buf, 0, sizeof(buf));
			}
		}while(read(sessionfd, buf+strlen(buf), sizeof(buf) - strlen(buf)) > 0);
		return createResponse(buf);
	}

	void load(string directory, string filename) noexcept{
		if(filename == "." || filename == "..") return;
		if(filename != "")
			directory += "/" + move(filename);
		DIR* dir = opendir(directory.c_str());
		if(dir != NULL){
			struct dirent* dent;
	        dent = readdir(dir);
		    while(dent!=NULL){
		        dent = readdir(dir);
		        if(dent!=NULL)
			        load(directory, string(dent->d_name));
		    }
			if(dir!=NULL){
		    	closedir(dir);
			}
		}else{
			Log::debug("add "+directory);
			context.routes.insert( make_pair(
				"/" + directory,
				[directory,filename](std::shared_ptr<Request> request) -> Cappuccino::Response{
					return Response(200,"OK","HTTP/1.1",openFile(directory).first);
				}
			));
		}
	}

	void loadStaticFiles() noexcept{
		load(*context.static_root,"");
	}

	void route(string url,std::function<Response(std::shared_ptr<Request>)> F){
		context.routes.insert( make_pair( move(url), move(F) ));
	}

	void root(string r){
		context.view_root =  make_shared<string>(move(r));
	}

	void resource(string s){
		context.static_root = make_shared<string>(move(s));
	}

	void run(){

		init_socket();
		signal_utils::init_signal();
		loadStaticFiles();

	    int cd[FD_SETSIZE];
		struct sockaddr_in client;
        int    fd;
        struct timeval tv;

	    for(int i = 0;i < FD_SETSIZE; i++){
	        cd[i] = 0;
	    }

	    while(1) {

	        tv.tv_sec = 0;
	        tv.tv_usec = 0;

	        memcpy(&context.mask2fds, &context.mask1fds, sizeof(context.mask1fds));

	        int select_result = select(FD_SETSIZE, &context.mask2fds, (fd_set *)0, (fd_set *)0, &tv);
	        if(select_result < 1) {
	            for(fd = 0; fd < FD_SETSIZE; fd++) {
	                if(cd[fd] == 1) {
	                    close(fd);
	                    FD_CLR(fd, &context.mask1fds);
	                    cd[fd] = 0;
	                }
	            }
	            continue;
	        }
			for(fd = 0; fd < FD_SETSIZE; fd++){
	            if(FD_ISSET(fd,&context.mask2fds)) {
	                if(fd == context.sockfd) {
	                	memset( &client, 0, sizeof(client));
						int len = sizeof(client);
						int clientfd = accept(context.sockfd,
							(struct sockaddr *)&client,(socklen_t *) &len);
						FD_SET(clientfd, &context.mask1fds);
	                }else {
	                    if(cd[fd] == 1) {
	                        close(fd);
	                        FD_CLR(fd, &context.mask1fds);
	                        cd[fd] = 0;
	                    } else {
							string response = receiveProcess(fd);
							write(fd, response.c_str(), response.size());
	                        cd[fd] = 1;
	                    }
	                }
	            }
	        }
	    }
	}

	void Cappuccino(int argc, char *argv[]) {
		option(argc, argv);
		context.view_root = make_shared<string>("");
		context.static_root = make_shared<string>("public");
	}
};

namespace Cocoa{
	using namespace Cappuccino;
	using namespace std;

	// Unit Test
	void testOpenFile(){
		auto res = openFile("html/index.html");
		auto lines = utils::split(res.first, "\n");
		assert(!lines.empty());
	}

	void testOpenInvalidFile(){
		try{
			auto res = openFile("html/index");
		}catch(std::runtime_error e){
			cout<< e.what() << endl;
		}
	}
};

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2016 Couchbase, Inc.
 *
 *   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.
 */

#include "config.h"
#include "user.h"
#include "cbsasl_internal.h"

#include <atomic>
#include <openssl/evp.h>
#include <platform/base64.h>
#include <platform/random.h>
#include <stdexcept>

std::atomic<int> IterationCount(4096);

/**
 * Generate a salt and store it base64 encoded into the salt
 */
void generateSalt(std::vector<uint8_t>& bytes, std::string& salt) {
    Couchbase::RandomGenerator randomGenerator(true);

    if (!randomGenerator.getBytes(bytes.data(), bytes.size())) {
        throw std::runtime_error("Failed to get random bytes");
    }

    using Couchbase::Base64::encode;

    salt = encode(std::string(reinterpret_cast<char*>(bytes.data()),
                              bytes.size()));
}

Couchbase::User::User(const std::string& unm, const std::string& passwd)
    : username(unm),
      plaintextPassword(passwd),
      iterationCount(IterationCount.load()),
      dummy(false) {

#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
    std::vector<uint8_t> salt(Sha1DigestSize);

    generateSalt(salt, sha1Salt);

    if (PKCS5_PBKDF2_HMAC_SHA1(passwd.data(), int(passwd.size()),
                               salt.data(), int(salt.size()),
                               iterationCount,
                               Sha1DigestSize,
                               saltedSha1Password.data()) != 1) {
        throw std::runtime_error("PKCS5_PBKDF2_HMAC_SHA1 failed");
    }
#endif

#ifdef HAVE_PKCS5_PBKDF2_HMAC
    // The version of OpenSSL shipped with MacOSX does not contain
    // PKCS5_PBKDF2_HMAC and I don't feel like creating an implementation
    // just for MacOSX (the customer base is too small and this is
    // a non-essential functionality)
    salt.resize(Sha256DigestSize);
    generateSalt(salt, sha256Salt);
    if (PKCS5_PBKDF2_HMAC(passwd.data(), int(passwd.size()),
                          salt.data(), int(salt.size()),
                          iterationCount,
                          EVP_sha256(),
                          Sha256DigestSize,
                          saltedSha256Password.data()) != 1) {
        throw std::runtime_error("PKCS5_PBKDF2_HMAC SHA256 failed");
    }

    salt.resize(Sha512DigestSize);
    generateSalt(salt, sha512Salt);
    if (PKCS5_PBKDF2_HMAC(passwd.data(), int(passwd.size()),
                          salt.data(), int(salt.size()),
                          iterationCount,
                          EVP_sha512(),
                          Sha512DigestSize,
                          saltedSha512Password.data()) != 1) {
        throw std::runtime_error("PKCS5_PBKDF2_HMAC SHA512 failed");
    }
#endif
}

void cbsasl_set_hmac_iteration_count(cbsasl_getopt_fn getopt_fn,
                                     void* context) {

    const char* result = nullptr;
    unsigned int result_len;

    if (getopt_fn(context, nullptr, "hmac iteration count", &result,
                  &result_len) == CBSASL_OK) {
        if (result != nullptr) {
            std::string val(result, result_len);
            try {
                IterationCount.store(std::stoi(val));
            } catch (...) {
                cbsasl_log(nullptr, cbsasl_loglevel_t::Error,
                           "Failed to update HMAC iteration count");
            }
        }
    }
}

void Couchbase::User::generateSecrets(const Mechanism& mech) {
    if (!dummy) {
        throw std::runtime_error("Couchbase::User::generateSecrets can't be "
                                     "used on a real user object");
    }

    std::vector<uint8_t> salt;
    std::string passwd;

    switch (mech) {
#ifdef HAVE_PKCS5_PBKDF2_HMAC
    case Mechanism::SCRAM_SHA512:
        salt.resize(Sha512DigestSize);
        generateSalt(salt, passwd);
        generateSalt(salt, sha512Salt);
        if (PKCS5_PBKDF2_HMAC(passwd.data(), int(passwd.size()),
                              salt.data(), int(salt.size()),
                              iterationCount,
                              EVP_sha512(),
                              Sha512DigestSize,
                              saltedSha512Password.data()) != 1) {
            throw std::runtime_error("PKCS5_PBKDF2_HMAC SHA512 failed");
        }
        break;
    case Mechanism::SCRAM_SHA256:
        salt.resize(Sha256DigestSize);
        generateSalt(salt, passwd);
        generateSalt(salt, sha256Salt);
        if (PKCS5_PBKDF2_HMAC(passwd.data(), int(passwd.size()),
                              salt.data(), int(salt.size()),
                              iterationCount,
                              EVP_sha256(),
                              Sha256DigestSize,
                              saltedSha256Password.data()) != 1) {
            throw std::runtime_error("PKCS5_PBKDF2_HMAC SHA256 failed");
        }
        break;
#endif
#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
        case Mechanism::SCRAM_SHA1:
        salt.resize(Sha1DigestSize);
        generateSalt(salt, passwd);
        generateSalt(salt, sha1Salt);
        if (PKCS5_PBKDF2_HMAC_SHA1(passwd.data(), int(passwd.size()),
                                   salt.data(), int(salt.size()),
                                   iterationCount,
                                   Sha1DigestSize,
                                   saltedSha1Password.data()) != 1) {
            throw std::runtime_error("PKCS5_PBKDF2_HMAC_SHA1 failed");
        }
        break;
#endif
    default:
        throw std::logic_error("Couchbase::User::generateSecrets invalid mech");
    }
}
<commit_msg>Use a low iteration count for SCRAM<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2016 Couchbase, Inc.
 *
 *   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.
 */

#include "config.h"
#include "user.h"
#include "cbsasl_internal.h"

#include <atomic>
#include <openssl/evp.h>
#include <platform/base64.h>
#include <platform/random.h>
#include <stdexcept>

// Reduce the iteration count to 10 while we're waiting for MB-17617
std::atomic<int> IterationCount(10);

/**
 * Generate a salt and store it base64 encoded into the salt
 */
void generateSalt(std::vector<uint8_t>& bytes, std::string& salt) {
    Couchbase::RandomGenerator randomGenerator(true);

    if (!randomGenerator.getBytes(bytes.data(), bytes.size())) {
        throw std::runtime_error("Failed to get random bytes");
    }

    using Couchbase::Base64::encode;

    salt = encode(std::string(reinterpret_cast<char*>(bytes.data()),
                              bytes.size()));
}

Couchbase::User::User(const std::string& unm, const std::string& passwd)
    : username(unm),
      plaintextPassword(passwd),
      iterationCount(IterationCount.load()),
      dummy(false) {

#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
    std::vector<uint8_t> salt(Sha1DigestSize);

    generateSalt(salt, sha1Salt);

    if (PKCS5_PBKDF2_HMAC_SHA1(passwd.data(), int(passwd.size()),
                               salt.data(), int(salt.size()),
                               iterationCount,
                               Sha1DigestSize,
                               saltedSha1Password.data()) != 1) {
        throw std::runtime_error("PKCS5_PBKDF2_HMAC_SHA1 failed");
    }
#endif

#ifdef HAVE_PKCS5_PBKDF2_HMAC
    // The version of OpenSSL shipped with MacOSX does not contain
    // PKCS5_PBKDF2_HMAC and I don't feel like creating an implementation
    // just for MacOSX (the customer base is too small and this is
    // a non-essential functionality)
    salt.resize(Sha256DigestSize);
    generateSalt(salt, sha256Salt);
    if (PKCS5_PBKDF2_HMAC(passwd.data(), int(passwd.size()),
                          salt.data(), int(salt.size()),
                          iterationCount,
                          EVP_sha256(),
                          Sha256DigestSize,
                          saltedSha256Password.data()) != 1) {
        throw std::runtime_error("PKCS5_PBKDF2_HMAC SHA256 failed");
    }

    salt.resize(Sha512DigestSize);
    generateSalt(salt, sha512Salt);
    if (PKCS5_PBKDF2_HMAC(passwd.data(), int(passwd.size()),
                          salt.data(), int(salt.size()),
                          iterationCount,
                          EVP_sha512(),
                          Sha512DigestSize,
                          saltedSha512Password.data()) != 1) {
        throw std::runtime_error("PKCS5_PBKDF2_HMAC SHA512 failed");
    }
#endif
}

void cbsasl_set_hmac_iteration_count(cbsasl_getopt_fn getopt_fn,
                                     void* context) {

    const char* result = nullptr;
    unsigned int result_len;

    if (getopt_fn(context, nullptr, "hmac iteration count", &result,
                  &result_len) == CBSASL_OK) {
        if (result != nullptr) {
            std::string val(result, result_len);
            try {
                IterationCount.store(std::stoi(val));
            } catch (...) {
                cbsasl_log(nullptr, cbsasl_loglevel_t::Error,
                           "Failed to update HMAC iteration count");
            }
        }
    }
}

void Couchbase::User::generateSecrets(const Mechanism& mech) {
    if (!dummy) {
        throw std::runtime_error("Couchbase::User::generateSecrets can't be "
                                     "used on a real user object");
    }

    std::vector<uint8_t> salt;
    std::string passwd;

    switch (mech) {
#ifdef HAVE_PKCS5_PBKDF2_HMAC
    case Mechanism::SCRAM_SHA512:
        salt.resize(Sha512DigestSize);
        generateSalt(salt, passwd);
        generateSalt(salt, sha512Salt);
        if (PKCS5_PBKDF2_HMAC(passwd.data(), int(passwd.size()),
                              salt.data(), int(salt.size()),
                              iterationCount,
                              EVP_sha512(),
                              Sha512DigestSize,
                              saltedSha512Password.data()) != 1) {
            throw std::runtime_error("PKCS5_PBKDF2_HMAC SHA512 failed");
        }
        break;
    case Mechanism::SCRAM_SHA256:
        salt.resize(Sha256DigestSize);
        generateSalt(salt, passwd);
        generateSalt(salt, sha256Salt);
        if (PKCS5_PBKDF2_HMAC(passwd.data(), int(passwd.size()),
                              salt.data(), int(salt.size()),
                              iterationCount,
                              EVP_sha256(),
                              Sha256DigestSize,
                              saltedSha256Password.data()) != 1) {
            throw std::runtime_error("PKCS5_PBKDF2_HMAC SHA256 failed");
        }
        break;
#endif
#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
        case Mechanism::SCRAM_SHA1:
        salt.resize(Sha1DigestSize);
        generateSalt(salt, passwd);
        generateSalt(salt, sha1Salt);
        if (PKCS5_PBKDF2_HMAC_SHA1(passwd.data(), int(passwd.size()),
                                   salt.data(), int(salt.size()),
                                   iterationCount,
                                   Sha1DigestSize,
                                   saltedSha1Password.data()) != 1) {
            throw std::runtime_error("PKCS5_PBKDF2_HMAC_SHA1 failed");
        }
        break;
#endif
    default:
        throw std::logic_error("Couchbase::User::generateSecrets invalid mech");
    }
}
<|endoftext|>