<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkIGTLDeviceSetupConnectionWidget.h"

//mitk headers
#include <mitkSurface.h>
#include <mitkIGTLDeviceSource.h>
#include <mitkDataStorage.h>
#include <mitkIGTLMessageFactory.h>

//qt headers
#include <qfiledialog.h>
#include <qinputdialog.h>
#include <qmessagebox.h>
#include <qscrollbar.h>

//igtl
#include <igtlStringMessage.h>
#include <igtlBindMessage.h>
#include <igtlQuaternionTrackingDataMessage.h>
#include <igtlTrackingDataMessage.h>

//poco headers
#include <Poco/Path.h>

const std::string QmitkIGTLDeviceSetupConnectionWidget::VIEW_ID =
"org.mitk.views.igtldevicesetupconnectionwidget";

QmitkIGTLDeviceSetupConnectionWidget::QmitkIGTLDeviceSetupConnectionWidget(
  QWidget* parent, Qt::WindowFlags f)
  : QWidget(parent, f), m_IsClient(false)
{
  m_Controls = nullptr;
  this->m_IGTLDevice = nullptr;
  CreateQtPartControl(this);
  m_NumSentFramesSinceLastUpdate = 0;
  m_NumReceivedFramesSinceLastUpdate = 0;
}

QmitkIGTLDeviceSetupConnectionWidget::~QmitkIGTLDeviceSetupConnectionWidget()
{
  this->RemoveObserver();
}

void QmitkIGTLDeviceSetupConnectionWidget::RemoveObserver()
{
  if (this->m_IGTLDevice.IsNotNull())
  {
    this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_MessageSentObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag);
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::CreateQtPartControl(QWidget *parent)
{
  if (!m_Controls)
  {
    // create GUI widgets
    m_Controls = new Ui::QmitkIGTLDeviceSetupConnectionWidgetControls;
    // setup GUI widgets
    m_Controls->setupUi(parent);
  }

  // set the validator for the ip edit box (values must be between 0 and 255 and
  // there are four of them, seperated with a point
  QRegExpValidator *v = new QRegExpValidator(this);
  QRegExp rx("((1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})\\.){3,3}(1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})");
  v->setRegExp(rx);
  m_Controls->editIP->setValidator(v);
  // set the validator for the port edit box (values must be between 1 and 65535)
  m_Controls->editPort->setValidator(new QIntValidator(1, 65535, this));

  m_FPSCalculationTimer.start(1000);

  //connect slots with signals
  CreateConnections();
}

void QmitkIGTLDeviceSetupConnectionWidget::CreateConnections()
{
  if (m_Controls)
  {
    // connect the widget items with the methods
    connect(m_Controls->butConnect, SIGNAL(clicked()),
      this, SLOT(OnConnect()));
    connect(m_Controls->editPort, SIGNAL(editingFinished()),
      this, SLOT(OnPortChanged()));
    connect(m_Controls->editIP, SIGNAL(editingFinished()),
      this, SLOT(OnHostnameChanged()));
    connect(m_Controls->bufferInMsgCheckBox, SIGNAL(stateChanged(int)),
      this, SLOT(OnBufferIncomingMessages(int)));
    connect(m_Controls->bufferOutMsgCheckBox, SIGNAL(stateChanged(int)),
      this, SLOT(OnBufferOutgoingMessages(int)));
    connect(&m_FPSCalculationTimer, SIGNAL(timeout()),
      this, SLOT(OnUpdateFPSLabel()));
    connect(m_Controls->logMessageDetailsCheckBox, SIGNAL(clicked()),
      this, SLOT(OnLogMessageDetailsCheckBoxClicked()));
  }
  //this is used for thread seperation, otherwise the worker thread would change the ui elements
  //which would cause an exception
  connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState()));
}

void QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged()
{
  emit AdaptGUIToStateSignal();
}

void QmitkIGTLDeviceSetupConnectionWidget::AdaptGUIToState()
{
  //check the validity of the device
  if (this->m_IGTLDevice.IsNull())
  {
    return;
  }

  //check the state of the device
  mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState();

  switch (state) {
  case mitk::IGTLDevice::Setup:
    if (!m_IsClient)
    {
      m_Controls->butConnect->setText("Go Online");
      this->m_Controls->editIP->setEnabled(false);
    }
    else
    {
      m_Controls->butConnect->setText("Connect");
      this->m_Controls->editIP->setEnabled(true);
    }
    this->m_Controls->editPort->setEnabled(true);
    this->m_Controls->logMessageStatusCheckBox->setChecked(false);
    this->m_Controls->logMessageDetailsCheckBox->setChecked(false);
    this->m_Controls->logMessageStatusCheckBox->setEnabled(false);
    this->m_Controls->logMessageDetailsCheckBox->setEnabled(false);
    this->m_Controls->bufferInMsgCheckBox->setEnabled(false);
    this->m_Controls->bufferOutMsgCheckBox->setEnabled(false);
    this->m_Controls->butConnect->setEnabled(true);
    this->m_Controls->fpsInLabel->setEnabled(false);
    this->m_Controls->fpsOutLabel->setEnabled(false);
    this->m_Controls->fpsInDescrLabel->setEnabled(false);
    this->m_Controls->fpsOutDescrLabel->setEnabled(false);

    if( this->m_IGTLDevice.IsNotNull() )
    {
      this->m_IGTLDevice->SetLogMessages(false);
    }

    break;
  case mitk::IGTLDevice::Ready:
    if (m_IsClient)
    {
      this->m_Controls->butConnect->setText("Disconnect");
    }
    else
    {
      this->m_Controls->butConnect->setText("Go Offline");
    }
    this->m_Controls->editIP->setEnabled(false);
    this->m_Controls->editPort->setEnabled(false);
    this->m_Controls->logMessageStatusCheckBox->setEnabled(true);
    this->m_Controls->logMessageDetailsCheckBox->setEnabled(true);
    this->m_Controls->bufferInMsgCheckBox->setEnabled(true);
    this->m_Controls->bufferOutMsgCheckBox->setEnabled(true);
    this->m_Controls->butConnect->setEnabled(true);
    this->m_Controls->fpsInLabel->setEnabled(true);
    this->m_Controls->fpsOutLabel->setEnabled(true);
    this->m_Controls->fpsInDescrLabel->setEnabled(true);
    this->m_Controls->fpsOutDescrLabel->setEnabled(true);
    break;
  case mitk::IGTLDevice::Running:
    if (m_IsClient)
    {
      this->m_Controls->butConnect->setText("Disconnect");
    }
    else
    {
      this->m_Controls->butConnect->setText("Go Offline");
    }
    this->m_Controls->editIP->setEnabled(false);
    this->m_Controls->editPort->setEnabled(false);
    this->m_Controls->logMessageStatusCheckBox->setEnabled(true);
    this->m_Controls->logMessageDetailsCheckBox->setEnabled(true);
    this->m_Controls->bufferInMsgCheckBox->setEnabled(true);
    this->m_Controls->bufferOutMsgCheckBox->setEnabled(true);
    this->m_Controls->butConnect->setEnabled(true);
    this->m_Controls->fpsInLabel->setEnabled(true);
    this->m_Controls->fpsOutLabel->setEnabled(true);
    this->m_Controls->fpsInDescrLabel->setEnabled(true);
    this->m_Controls->fpsOutDescrLabel->setEnabled(true);
    break;
  default:
    mitkThrow() << "Invalid Device State";
    break;
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::Initialize(
  mitk::IGTLDevice::Pointer device)
{
  //reset the GUI
  DisableSourceControls();
  //reset the observers
  this->RemoveObserver();

  if (device.IsNotNull())
  {
    this->m_IGTLDevice = device;

    //check if the device is a server or a client
    if (dynamic_cast<mitk::IGTLClient*>(
      this->m_IGTLDevice.GetPointer()) == nullptr)
    {
      m_IsClient = false;
    }
    else
    {
      m_IsClient = true;
    }

    this->AdaptGUIToState();

    typedef itk::SimpleMemberCommand< QmitkIGTLDeviceSetupConnectionWidget > CurCommandType;
    CurCommandType::Pointer messageSentCommand = CurCommandType::New();
    messageSentCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageSent);
    this->m_MessageSentObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::MessageSentEvent(), messageSentCommand);

    CurCommandType::Pointer messageReceivedCommand = CurCommandType::New();
    messageReceivedCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived);
    this->m_MessageReceivedObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::MessageReceivedEvent(), messageReceivedCommand);

    CurCommandType::Pointer commandReceivedCommand = CurCommandType::New();
    commandReceivedCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived);
    this->m_CommandReceivedObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::CommandReceivedEvent(), commandReceivedCommand);

    CurCommandType::Pointer connectionLostCommand = CurCommandType::New();
    connectionLostCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection);
    this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::LostConnectionEvent(), connectionLostCommand);

    CurCommandType::Pointer newConnectionCommand = CurCommandType::New();
    newConnectionCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection);
    this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::NewClientConnectionEvent(), newConnectionCommand);

    CurCommandType::Pointer stateModifiedCommand = CurCommandType::New();
    stateModifiedCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged);
    this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver(
      itk::ModifiedEvent(), stateModifiedCommand);

    OnBufferIncomingMessages(m_Controls->bufferInMsgCheckBox->isChecked());
    OnBufferOutgoingMessages(m_Controls->bufferOutMsgCheckBox->isChecked());
  }
  else
  {
    m_IGTLDevice = nullptr;
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::DisableSourceControls()
{
  m_Controls->editIP->setEnabled(false);
  m_Controls->editPort->setEnabled(false);
  m_Controls->butConnect->setEnabled(false);
  m_Controls->bufferInMsgCheckBox->setEnabled(false);
  m_Controls->bufferOutMsgCheckBox->setEnabled(false);
  this->m_Controls->logMessageStatusCheckBox->setChecked(false);
  this->m_Controls->logMessageDetailsCheckBox->setChecked(false);
  this->m_Controls->logMessageStatusCheckBox->setEnabled(false);
  this->m_Controls->logMessageDetailsCheckBox->setEnabled(false);

  if( this->m_IGTLDevice.IsNotNull() )
  {
    this->m_IGTLDevice->SetLogMessages(false);
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::OnConnect()
{
  if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Setup)
  {
    QString port = m_Controls->editPort->text();
    m_IGTLDevice->SetPortNumber(port.toInt());
    std::string hostname = m_Controls->editIP->text().toStdString();
    m_IGTLDevice->SetHostname(hostname);
    //connect with the other OpenIGTLink device => changes the state from Setup
    //to Ready
    if (m_IGTLDevice->OpenConnection())
    {
      //starts the communication thread => changes the state from Ready to
      //Running
      if (m_IGTLDevice->StartCommunication())
      {
        if (this->m_IsClient)
        {
          MITK_INFO("IGTLDeviceSourceManagementWidget")
            << "Successfully connected to " << hostname
            << " on port " << port.toStdString();
        }
      }
      else
      {
        MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") <<
          "Could not start a communication with the"
          "server because the client is in the wrong state";
      }
    }
    else
    {
      MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") <<
        "Could not connect to the server. "
        "Please check the hostname and port.";
    }
  }
  else if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready || m_IGTLDevice->GetState() == mitk::IGTLDevice::Running)
  {
    m_IGTLDevice->CloseConnection();
    MITK_INFO("QmitkIGTLDeviceSetupConnectionWidget") << "Closed connection";
  }
  else
  {
    mitkThrow() << "Invalid state of IGTLDevice";
  }
  this->AdaptGUIToState();
}

void QmitkIGTLDeviceSetupConnectionWidget::OnPortChanged()
{
}

void QmitkIGTLDeviceSetupConnectionWidget::OnHostnameChanged()
{
}

void QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection()
{
  emit AdaptGUIToStateSignal();
}

void QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection()
{
  emit AdaptGUIToStateSignal();
}

void QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived()
{
  if( this->m_Controls->logMessageStatusCheckBox->isChecked() )
  {
    MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a message.";
  }
  m_NumReceivedFramesSinceLastUpdate++;
}

void QmitkIGTLDeviceSetupConnectionWidget::OnMessageSent()
{
  if( this->m_Controls->logMessageStatusCheckBox->isChecked() )
  {
    MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Sent a message.";
  }
  m_NumSentFramesSinceLastUpdate++;
}

void QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived()
{
  if( this->m_Controls->logMessageStatusCheckBox->isChecked() )
  {
    MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a command.";
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::OnBufferIncomingMessages(int state)
{
  if (this->m_IGTLDevice.IsNotNull())
  {
    this->m_IGTLDevice->EnableNoBufferingMode(
      this->m_IGTLDevice->GetMessageQueue(), (bool)state);
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::OnBufferOutgoingMessages(int state)
{
  if (this->m_IGTLDevice.IsNotNull())
  {
    this->m_IGTLDevice->EnableNoBufferingMode(
      this->m_IGTLDevice->GetMessageQueue(), (bool)state);
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::OnUpdateFPSLabel()
{
  double fpsIn = m_NumReceivedFramesSinceLastUpdate / 1.0;
  double fpsOut = m_NumSentFramesSinceLastUpdate / 1.0;
  this->m_Controls->fpsInLabel->setText(QString::number(fpsIn));
  this->m_Controls->fpsOutLabel->setText(QString::number(fpsOut));
  m_NumReceivedFramesSinceLastUpdate = 0;
  m_NumSentFramesSinceLastUpdate = 0;
}

void QmitkIGTLDeviceSetupConnectionWidget::OnLogMessageDetailsCheckBoxClicked()
{
  if( this->m_IGTLDevice.IsNull() )
  {
    MITK_WARN << "Logging information not passed down to Message Provider.";
    return;
  }
  else
  {
    this->m_IGTLDevice->SetLogMessages( this->m_Controls->logMessageDetailsCheckBox->isChecked() );
  }
}
<commit_msg>Add missing include file<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "QmitkIGTLDeviceSetupConnectionWidget.h"

//mitk headers
#include <mitkSurface.h>
#include <mitkIGTLDeviceSource.h>
#include <mitkDataStorage.h>
#include <mitkIGTLMessageFactory.h>

//qt headers
#include <qfiledialog.h>
#include <qinputdialog.h>
#include <qmessagebox.h>
#include <qscrollbar.h>

//igtl
#include <igtlStringMessage.h>
#include <igtlBindMessage.h>
#include <igtlQuaternionTrackingDataMessage.h>
#include <igtlTrackingDataMessage.h>

//poco headers
#include <Poco/Path.h>

#include <QRegExpValidator>

const std::string QmitkIGTLDeviceSetupConnectionWidget::VIEW_ID =
"org.mitk.views.igtldevicesetupconnectionwidget";

QmitkIGTLDeviceSetupConnectionWidget::QmitkIGTLDeviceSetupConnectionWidget(
  QWidget* parent, Qt::WindowFlags f)
  : QWidget(parent, f), m_IsClient(false)
{
  m_Controls = nullptr;
  this->m_IGTLDevice = nullptr;
  CreateQtPartControl(this);
  m_NumSentFramesSinceLastUpdate = 0;
  m_NumReceivedFramesSinceLastUpdate = 0;
}

QmitkIGTLDeviceSetupConnectionWidget::~QmitkIGTLDeviceSetupConnectionWidget()
{
  this->RemoveObserver();
}

void QmitkIGTLDeviceSetupConnectionWidget::RemoveObserver()
{
  if (this->m_IGTLDevice.IsNotNull())
  {
    this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_MessageSentObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag);
    this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag);
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::CreateQtPartControl(QWidget *parent)
{
  if (!m_Controls)
  {
    // create GUI widgets
    m_Controls = new Ui::QmitkIGTLDeviceSetupConnectionWidgetControls;
    // setup GUI widgets
    m_Controls->setupUi(parent);
  }

  // set the validator for the ip edit box (values must be between 0 and 255 and
  // there are four of them, seperated with a point
  QRegExpValidator *v = new QRegExpValidator(this);
  QRegExp rx("((1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})\\.){3,3}(1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})");
  v->setRegExp(rx);
  m_Controls->editIP->setValidator(v);
  // set the validator for the port edit box (values must be between 1 and 65535)
  m_Controls->editPort->setValidator(new QIntValidator(1, 65535, this));

  m_FPSCalculationTimer.start(1000);

  //connect slots with signals
  CreateConnections();
}

void QmitkIGTLDeviceSetupConnectionWidget::CreateConnections()
{
  if (m_Controls)
  {
    // connect the widget items with the methods
    connect(m_Controls->butConnect, SIGNAL(clicked()),
      this, SLOT(OnConnect()));
    connect(m_Controls->editPort, SIGNAL(editingFinished()),
      this, SLOT(OnPortChanged()));
    connect(m_Controls->editIP, SIGNAL(editingFinished()),
      this, SLOT(OnHostnameChanged()));
    connect(m_Controls->bufferInMsgCheckBox, SIGNAL(stateChanged(int)),
      this, SLOT(OnBufferIncomingMessages(int)));
    connect(m_Controls->bufferOutMsgCheckBox, SIGNAL(stateChanged(int)),
      this, SLOT(OnBufferOutgoingMessages(int)));
    connect(&m_FPSCalculationTimer, SIGNAL(timeout()),
      this, SLOT(OnUpdateFPSLabel()));
    connect(m_Controls->logMessageDetailsCheckBox, SIGNAL(clicked()),
      this, SLOT(OnLogMessageDetailsCheckBoxClicked()));
  }
  //this is used for thread seperation, otherwise the worker thread would change the ui elements
  //which would cause an exception
  connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState()));
}

void QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged()
{
  emit AdaptGUIToStateSignal();
}

void QmitkIGTLDeviceSetupConnectionWidget::AdaptGUIToState()
{
  //check the validity of the device
  if (this->m_IGTLDevice.IsNull())
  {
    return;
  }

  //check the state of the device
  mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState();

  switch (state) {
  case mitk::IGTLDevice::Setup:
    if (!m_IsClient)
    {
      m_Controls->butConnect->setText("Go Online");
      this->m_Controls->editIP->setEnabled(false);
    }
    else
    {
      m_Controls->butConnect->setText("Connect");
      this->m_Controls->editIP->setEnabled(true);
    }
    this->m_Controls->editPort->setEnabled(true);
    this->m_Controls->logMessageStatusCheckBox->setChecked(false);
    this->m_Controls->logMessageDetailsCheckBox->setChecked(false);
    this->m_Controls->logMessageStatusCheckBox->setEnabled(false);
    this->m_Controls->logMessageDetailsCheckBox->setEnabled(false);
    this->m_Controls->bufferInMsgCheckBox->setEnabled(false);
    this->m_Controls->bufferOutMsgCheckBox->setEnabled(false);
    this->m_Controls->butConnect->setEnabled(true);
    this->m_Controls->fpsInLabel->setEnabled(false);
    this->m_Controls->fpsOutLabel->setEnabled(false);
    this->m_Controls->fpsInDescrLabel->setEnabled(false);
    this->m_Controls->fpsOutDescrLabel->setEnabled(false);

    if( this->m_IGTLDevice.IsNotNull() )
    {
      this->m_IGTLDevice->SetLogMessages(false);
    }

    break;
  case mitk::IGTLDevice::Ready:
    if (m_IsClient)
    {
      this->m_Controls->butConnect->setText("Disconnect");
    }
    else
    {
      this->m_Controls->butConnect->setText("Go Offline");
    }
    this->m_Controls->editIP->setEnabled(false);
    this->m_Controls->editPort->setEnabled(false);
    this->m_Controls->logMessageStatusCheckBox->setEnabled(true);
    this->m_Controls->logMessageDetailsCheckBox->setEnabled(true);
    this->m_Controls->bufferInMsgCheckBox->setEnabled(true);
    this->m_Controls->bufferOutMsgCheckBox->setEnabled(true);
    this->m_Controls->butConnect->setEnabled(true);
    this->m_Controls->fpsInLabel->setEnabled(true);
    this->m_Controls->fpsOutLabel->setEnabled(true);
    this->m_Controls->fpsInDescrLabel->setEnabled(true);
    this->m_Controls->fpsOutDescrLabel->setEnabled(true);
    break;
  case mitk::IGTLDevice::Running:
    if (m_IsClient)
    {
      this->m_Controls->butConnect->setText("Disconnect");
    }
    else
    {
      this->m_Controls->butConnect->setText("Go Offline");
    }
    this->m_Controls->editIP->setEnabled(false);
    this->m_Controls->editPort->setEnabled(false);
    this->m_Controls->logMessageStatusCheckBox->setEnabled(true);
    this->m_Controls->logMessageDetailsCheckBox->setEnabled(true);
    this->m_Controls->bufferInMsgCheckBox->setEnabled(true);
    this->m_Controls->bufferOutMsgCheckBox->setEnabled(true);
    this->m_Controls->butConnect->setEnabled(true);
    this->m_Controls->fpsInLabel->setEnabled(true);
    this->m_Controls->fpsOutLabel->setEnabled(true);
    this->m_Controls->fpsInDescrLabel->setEnabled(true);
    this->m_Controls->fpsOutDescrLabel->setEnabled(true);
    break;
  default:
    mitkThrow() << "Invalid Device State";
    break;
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::Initialize(
  mitk::IGTLDevice::Pointer device)
{
  //reset the GUI
  DisableSourceControls();
  //reset the observers
  this->RemoveObserver();

  if (device.IsNotNull())
  {
    this->m_IGTLDevice = device;

    //check if the device is a server or a client
    if (dynamic_cast<mitk::IGTLClient*>(
      this->m_IGTLDevice.GetPointer()) == nullptr)
    {
      m_IsClient = false;
    }
    else
    {
      m_IsClient = true;
    }

    this->AdaptGUIToState();

    typedef itk::SimpleMemberCommand< QmitkIGTLDeviceSetupConnectionWidget > CurCommandType;
    CurCommandType::Pointer messageSentCommand = CurCommandType::New();
    messageSentCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageSent);
    this->m_MessageSentObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::MessageSentEvent(), messageSentCommand);

    CurCommandType::Pointer messageReceivedCommand = CurCommandType::New();
    messageReceivedCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived);
    this->m_MessageReceivedObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::MessageReceivedEvent(), messageReceivedCommand);

    CurCommandType::Pointer commandReceivedCommand = CurCommandType::New();
    commandReceivedCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived);
    this->m_CommandReceivedObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::CommandReceivedEvent(), commandReceivedCommand);

    CurCommandType::Pointer connectionLostCommand = CurCommandType::New();
    connectionLostCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection);
    this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::LostConnectionEvent(), connectionLostCommand);

    CurCommandType::Pointer newConnectionCommand = CurCommandType::New();
    newConnectionCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection);
    this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver(
      mitk::NewClientConnectionEvent(), newConnectionCommand);

    CurCommandType::Pointer stateModifiedCommand = CurCommandType::New();
    stateModifiedCommand->SetCallbackFunction(
      this, &QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged);
    this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver(
      itk::ModifiedEvent(), stateModifiedCommand);

    OnBufferIncomingMessages(m_Controls->bufferInMsgCheckBox->isChecked());
    OnBufferOutgoingMessages(m_Controls->bufferOutMsgCheckBox->isChecked());
  }
  else
  {
    m_IGTLDevice = nullptr;
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::DisableSourceControls()
{
  m_Controls->editIP->setEnabled(false);
  m_Controls->editPort->setEnabled(false);
  m_Controls->butConnect->setEnabled(false);
  m_Controls->bufferInMsgCheckBox->setEnabled(false);
  m_Controls->bufferOutMsgCheckBox->setEnabled(false);
  this->m_Controls->logMessageStatusCheckBox->setChecked(false);
  this->m_Controls->logMessageDetailsCheckBox->setChecked(false);
  this->m_Controls->logMessageStatusCheckBox->setEnabled(false);
  this->m_Controls->logMessageDetailsCheckBox->setEnabled(false);

  if( this->m_IGTLDevice.IsNotNull() )
  {
    this->m_IGTLDevice->SetLogMessages(false);
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::OnConnect()
{
  if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Setup)
  {
    QString port = m_Controls->editPort->text();
    m_IGTLDevice->SetPortNumber(port.toInt());
    std::string hostname = m_Controls->editIP->text().toStdString();
    m_IGTLDevice->SetHostname(hostname);
    //connect with the other OpenIGTLink device => changes the state from Setup
    //to Ready
    if (m_IGTLDevice->OpenConnection())
    {
      //starts the communication thread => changes the state from Ready to
      //Running
      if (m_IGTLDevice->StartCommunication())
      {
        if (this->m_IsClient)
        {
          MITK_INFO("IGTLDeviceSourceManagementWidget")
            << "Successfully connected to " << hostname
            << " on port " << port.toStdString();
        }
      }
      else
      {
        MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") <<
          "Could not start a communication with the"
          "server because the client is in the wrong state";
      }
    }
    else
    {
      MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") <<
        "Could not connect to the server. "
        "Please check the hostname and port.";
    }
  }
  else if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready || m_IGTLDevice->GetState() == mitk::IGTLDevice::Running)
  {
    m_IGTLDevice->CloseConnection();
    MITK_INFO("QmitkIGTLDeviceSetupConnectionWidget") << "Closed connection";
  }
  else
  {
    mitkThrow() << "Invalid state of IGTLDevice";
  }
  this->AdaptGUIToState();
}

void QmitkIGTLDeviceSetupConnectionWidget::OnPortChanged()
{
}

void QmitkIGTLDeviceSetupConnectionWidget::OnHostnameChanged()
{
}

void QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection()
{
  emit AdaptGUIToStateSignal();
}

void QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection()
{
  emit AdaptGUIToStateSignal();
}

void QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived()
{
  if( this->m_Controls->logMessageStatusCheckBox->isChecked() )
  {
    MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a message.";
  }
  m_NumReceivedFramesSinceLastUpdate++;
}

void QmitkIGTLDeviceSetupConnectionWidget::OnMessageSent()
{
  if( this->m_Controls->logMessageStatusCheckBox->isChecked() )
  {
    MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Sent a message.";
  }
  m_NumSentFramesSinceLastUpdate++;
}

void QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived()
{
  if( this->m_Controls->logMessageStatusCheckBox->isChecked() )
  {
    MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a command.";
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::OnBufferIncomingMessages(int state)
{
  if (this->m_IGTLDevice.IsNotNull())
  {
    this->m_IGTLDevice->EnableNoBufferingMode(
      this->m_IGTLDevice->GetMessageQueue(), (bool)state);
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::OnBufferOutgoingMessages(int state)
{
  if (this->m_IGTLDevice.IsNotNull())
  {
    this->m_IGTLDevice->EnableNoBufferingMode(
      this->m_IGTLDevice->GetMessageQueue(), (bool)state);
  }
}

void QmitkIGTLDeviceSetupConnectionWidget::OnUpdateFPSLabel()
{
  double fpsIn = m_NumReceivedFramesSinceLastUpdate / 1.0;
  double fpsOut = m_NumSentFramesSinceLastUpdate / 1.0;
  this->m_Controls->fpsInLabel->setText(QString::number(fpsIn));
  this->m_Controls->fpsOutLabel->setText(QString::number(fpsOut));
  m_NumReceivedFramesSinceLastUpdate = 0;
  m_NumSentFramesSinceLastUpdate = 0;
}

void QmitkIGTLDeviceSetupConnectionWidget::OnLogMessageDetailsCheckBoxClicked()
{
  if( this->m_IGTLDevice.IsNull() )
  {
    MITK_WARN << "Logging information not passed down to Message Provider.";
    return;
  }
  else
  {
    this->m_IGTLDevice->SetLogMessages( this->m_Controls->logMessageDetailsCheckBox->isChecked() );
  }
}
<|endoftext|>


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

#include "xdgbasedirs_p.h"

#include "akonadi-prefix.h" // for prefix defines

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>

#include <cstdlib>

static QStringList alternateExecPaths( const QString& path )
{
  QStringList pathList;

  pathList << path;

#if defined(Q_OS_WIN) //krazy:exclude=cpp
  pathList << path + QLatin1String( ".exe" );
#elif defined(Q_OS_MAC) //krazy:exclude=cpp
  pathList << path + QLatin1String( ".app/Contents/MacOS/" ) + path.section( QLatin1Char( '/' ), -1 );
#endif

  return pathList;
}

static QStringList splitPathList( const QString &pathList )
{
#if defined(Q_OS_WIN) //krazy:exclude=cpp
  return pathList.split( QLatin1Char( ';' ) );
#else
  return pathList.split( QLatin1Char( ':' ) );
#endif
}

namespace Akonadi {

class XdgBaseDirsPrivate
{
  public:
    XdgBaseDirsPrivate() {}

    ~XdgBaseDirsPrivate() {}
};

class XdgBaseDirsSingleton
{
public:
    QString homePath( const char *variable, const char *defaultSubDir );

    QStringList systemPathList( const char *variable, const char *defaultDirList );

  public:
    QString mConfigHome;
    QString mDataHome;

    QStringList mConfigDirs;
    QStringList mDataDirs;
    QStringList mExecutableDirs;
};

Q_GLOBAL_STATIC(XdgBaseDirsSingleton, instance)

}

using namespace Akonadi;

XdgBaseDirs::XdgBaseDirs() : d( new XdgBaseDirsPrivate() )
{
}

XdgBaseDirs::~XdgBaseDirs()
{
  delete d;
}

QString XdgBaseDirs::homePath( const char *resource )
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( instance()->mDataHome.isEmpty() ) {
      instance()->mDataHome = instance()->homePath( "XDG_DATA_HOME", ".local/share" );
    }
    return instance()->mDataHome;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( instance()->mConfigHome.isEmpty() ) {
      instance()->mConfigHome = instance()->homePath( "XDG_CONFIG_HOME", ".config" );
    }
    return instance()->mConfigHome;
  }

  return QString();
}

QStringList XdgBaseDirs::systemPathList( const char *resource )
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( instance()->mDataDirs.isEmpty() ) {
      QStringList dataDirs = instance()->systemPathList( "XDG_DATA_DIRS", "/usr/local/share:/usr/share" );

#ifdef Q_OS_WIN
      const QString prefixDataDir = QLatin1String( AKONADIPREFIX "/" AKONADIDATA );
#else
      const QString prefixDataDir = QLatin1String( AKONADIDATA );
#endif
      if ( !dataDirs.contains( prefixDataDir ) ) {
        dataDirs << prefixDataDir;
      }

      // fallback for users with KDE in a different prefix and not correctly set up XDG_DATA_DIRS, hi David ;-)
      QProcess proc;
      // ### should probably rather be --path xdg-something
      const QStringList args = QStringList() << QLatin1String( "--prefix" );
      proc.start( QLatin1String( "kde4-config" ), args );
      if ( proc.waitForStarted() && proc.waitForFinished() && proc.exitCode() == 0 ) {
        proc.setReadChannel( QProcess::StandardOutput );
        foreach ( const QString &basePath, splitPathList( QString::fromLocal8Bit( proc.readLine().trimmed() ) ) ) {
          const QString path = basePath + QDir::separator() + QLatin1String( "share" );
          if ( !dataDirs.contains( path ) )
            dataDirs << path;
        }
      }

      instance()->mDataDirs = dataDirs;
    }
    return instance()->mDataDirs;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( instance()->mConfigDirs.isEmpty() ) {
      QStringList configDirs = instance()->systemPathList( "XDG_CONFIG_DIRS", "/etc/xdg" );

#ifdef Q_OS_WIN
      const QString prefixConfigDir = QLatin1String( AKONADIPREFIX "/" AKONADICONFIG );
#else
      const QString prefixConfigDir = QLatin1String( AKONADICONFIG );
#endif
      if ( !configDirs.contains( prefixConfigDir ) ) {
        configDirs << prefixConfigDir;
      }

      instance()->mConfigDirs = configDirs;
    }
    return instance()->mConfigDirs;
  }

  return QStringList();
}

QString XdgBaseDirs::findResourceFile( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QString XdgBaseDirs::findExecutableFile( const QString &relPath, const QStringList &searchPath )
{
  if ( instance()->mExecutableDirs.isEmpty() ) {
    QStringList executableDirs = instance()->systemPathList( "PATH", "/usr/local/bin:/usr/bin" );

    const QString prefixExecutableDir = QLatin1String( AKONADIPREFIX "/bin" );
    if ( !executableDirs.contains( prefixExecutableDir ) ) {
      executableDirs << prefixExecutableDir;
    }

    executableDirs += searchPath;

#if defined(Q_OS_MAC) //krazy:exclude=cpp
    executableDirs += QLatin1String(AKONADIBUNDLEPATH);
#endif
    qWarning( ) << "search paths: " << executableDirs;

    instance()->mExecutableDirs = executableDirs;
  }

  QStringList::const_iterator pathIt    = instance()->mExecutableDirs.constBegin();
  QStringList::const_iterator pathEndIt = instance()->mExecutableDirs.constEnd();
  for ( ; pathIt != pathEndIt; ++pathIt ) {
    QStringList fullPathList = alternateExecPaths(*pathIt + QLatin1Char( '/' ) + relPath );

    QStringList::const_iterator it    = fullPathList.constBegin();
    QStringList::const_iterator endIt = fullPathList.constEnd();
    for ( ; it != endIt; ++it ) {
      const QFileInfo fileInfo( *it );

      // resolve symlinks, happens eg. with Maemo optify
      if ( fileInfo.canonicalFilePath().isEmpty() )
        continue;
      const QFileInfo canonicalFileInfo( fileInfo.canonicalFilePath() );

      if ( canonicalFileInfo.exists() && canonicalFileInfo.isFile() && canonicalFileInfo.isExecutable() ) {
        return *it;
      }
    }
  }

  return QString();
}

QString XdgBaseDirs::findResourceDir( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QStringList XdgBaseDirs::findAllResourceDirs( const char *resource, const QString &relPath )
{
  QStringList resultList;

  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    resultList << fileInfo.absoluteFilePath();
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      resultList << fileInfo.absoluteFilePath();
    }
  }

  return resultList;
}

QString XdgBaseDirs::saveDir( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() ) {
    if ( fileInfo.isDir() ) {
      return fullPath;
    } else {
      qWarning() << "XdgBaseDirs::saveDir: '" << fileInfo.absoluteFilePath()
                 << "' exists but is not a directory";
    }
  } else {
    if ( !QDir::home().mkpath( fileInfo.absoluteFilePath() ) ) {
      qWarning() << "XdgBaseDirs::saveDir: failed to create directory '"
                 << fileInfo.absoluteFilePath() << "'";
    } else {
      return fullPath;
    }
  }

  return QString();
}

QString XdgBaseDirs::akonadiServerConfigFile( FileAccessMode openMode )
{
  return akonadiConfigFile( QLatin1String( "akonadiserverrc" ), openMode );
}

QString XdgBaseDirs::akonadiConnectionConfigFile( FileAccessMode openMode )
{
  return akonadiConfigFile( QLatin1String( "akonadiconnectionrc" ), openMode );
}

QString XdgBaseDirs::akonadiConfigFile( const QString &file, FileAccessMode openMode )
{
  const QString akonadiDir = QLatin1String( "akonadi" );

  QString savePath = saveDir( "config", akonadiDir ) + QLatin1Char( '/' ) + file;

  if ( openMode == WriteOnly ) return savePath;

  QString path = findResourceFile( "config", akonadiDir + QLatin1Char( '/' ) + file );

  if ( path.isEmpty() ) {
    return savePath;
  } else if ( openMode == ReadOnly || path == savePath ) {
    return path;
  }

  // file found in system paths and mode is ReadWrite, thus
  // we copy to the home path location and return this path
  QFile systemFile( path );

  systemFile.copy( savePath );

  return savePath;
}

QString XdgBaseDirsSingleton::homePath( const char *variable, const char *defaultSubDir )
{
  const QByteArray env = qgetenv( variable );

  QString xdgPath;
  if ( env.isEmpty() ) {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QLatin1String( defaultSubDir );
#if defined(Q_OS_WIN) //krazy:exclude=cpp
  } else if ( QDir::isAbsolutePath( QString::fromLocal8Bit( env ) ) ) {
#else
  } else if ( env.startsWith( '/' ) ) {
#endif
    xdgPath = QString::fromLocal8Bit( env );
  } else {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QString::fromLocal8Bit( env );
  }

  return xdgPath;
}

QStringList XdgBaseDirsSingleton::systemPathList( const char *variable, const char *defaultDirList )
{
  const QByteArray env = qgetenv( variable );

  QString xdgDirList;
  if ( env.isEmpty() ) {
    xdgDirList = QLatin1String( defaultDirList );
  } else {
    xdgDirList = QString::fromLocal8Bit( env );
  }

  return splitPathList( xdgDirList );
}
<commit_msg>If we have a QCoreApplication instance, add the current programs application path to the search list for executables if it is not in the list yet. Helps on Windows when tool programs are installed together but into a location which is not in PATH<commit_after>/***************************************************************************
 *   Copyright (C) 2007 by Kevin Krammer <kevin.krammer@gmx.at>            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/

#include "xdgbasedirs_p.h"

#include "akonadi-prefix.h" // for prefix defines

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>

#include <cstdlib>

static QStringList alternateExecPaths( const QString& path )
{
  QStringList pathList;

  pathList << path;

#if defined(Q_OS_WIN) //krazy:exclude=cpp
  pathList << path + QLatin1String( ".exe" );
#elif defined(Q_OS_MAC) //krazy:exclude=cpp
  pathList << path + QLatin1String( ".app/Contents/MacOS/" ) + path.section( QLatin1Char( '/' ), -1 );
#endif

  return pathList;
}

static QStringList splitPathList( const QString &pathList )
{
#if defined(Q_OS_WIN) //krazy:exclude=cpp
  return pathList.split( QLatin1Char( ';' ) );
#else
  return pathList.split( QLatin1Char( ':' ) );
#endif
}

namespace Akonadi {

class XdgBaseDirsPrivate
{
  public:
    XdgBaseDirsPrivate() {}

    ~XdgBaseDirsPrivate() {}
};

class XdgBaseDirsSingleton
{
public:
    QString homePath( const char *variable, const char *defaultSubDir );

    QStringList systemPathList( const char *variable, const char *defaultDirList );

  public:
    QString mConfigHome;
    QString mDataHome;

    QStringList mConfigDirs;
    QStringList mDataDirs;
    QStringList mExecutableDirs;
};

Q_GLOBAL_STATIC(XdgBaseDirsSingleton, instance)

}

using namespace Akonadi;

XdgBaseDirs::XdgBaseDirs() : d( new XdgBaseDirsPrivate() )
{
}

XdgBaseDirs::~XdgBaseDirs()
{
  delete d;
}

QString XdgBaseDirs::homePath( const char *resource )
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( instance()->mDataHome.isEmpty() ) {
      instance()->mDataHome = instance()->homePath( "XDG_DATA_HOME", ".local/share" );
    }
    return instance()->mDataHome;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( instance()->mConfigHome.isEmpty() ) {
      instance()->mConfigHome = instance()->homePath( "XDG_CONFIG_HOME", ".config" );
    }
    return instance()->mConfigHome;
  }

  return QString();
}

QStringList XdgBaseDirs::systemPathList( const char *resource )
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( instance()->mDataDirs.isEmpty() ) {
      QStringList dataDirs = instance()->systemPathList( "XDG_DATA_DIRS", "/usr/local/share:/usr/share" );

#ifdef Q_OS_WIN
      const QString prefixDataDir = QLatin1String( AKONADIPREFIX "/" AKONADIDATA );
#else
      const QString prefixDataDir = QLatin1String( AKONADIDATA );
#endif
      if ( !dataDirs.contains( prefixDataDir ) ) {
        dataDirs << prefixDataDir;
      }

      // fallback for users with KDE in a different prefix and not correctly set up XDG_DATA_DIRS, hi David ;-)
      QProcess proc;
      // ### should probably rather be --path xdg-something
      const QStringList args = QStringList() << QLatin1String( "--prefix" );
      proc.start( QLatin1String( "kde4-config" ), args );
      if ( proc.waitForStarted() && proc.waitForFinished() && proc.exitCode() == 0 ) {
        proc.setReadChannel( QProcess::StandardOutput );
        foreach ( const QString &basePath, splitPathList( QString::fromLocal8Bit( proc.readLine().trimmed() ) ) ) {
          const QString path = basePath + QDir::separator() + QLatin1String( "share" );
          if ( !dataDirs.contains( path ) )
            dataDirs << path;
        }
      }

      instance()->mDataDirs = dataDirs;
    }
    return instance()->mDataDirs;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( instance()->mConfigDirs.isEmpty() ) {
      QStringList configDirs = instance()->systemPathList( "XDG_CONFIG_DIRS", "/etc/xdg" );

#ifdef Q_OS_WIN
      const QString prefixConfigDir = QLatin1String( AKONADIPREFIX "/" AKONADICONFIG );
#else
      const QString prefixConfigDir = QLatin1String( AKONADICONFIG );
#endif
      if ( !configDirs.contains( prefixConfigDir ) ) {
        configDirs << prefixConfigDir;
      }

      instance()->mConfigDirs = configDirs;
    }
    return instance()->mConfigDirs;
  }

  return QStringList();
}

QString XdgBaseDirs::findResourceFile( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QString XdgBaseDirs::findExecutableFile( const QString &relPath, const QStringList &searchPath )
{
  if ( instance()->mExecutableDirs.isEmpty() ) {
    QStringList executableDirs = instance()->systemPathList( "PATH", "/usr/local/bin:/usr/bin" );

    const QString prefixExecutableDir = QLatin1String( AKONADIPREFIX "/bin" );
    if ( !executableDirs.contains( prefixExecutableDir ) ) {
      executableDirs << prefixExecutableDir;
    }

    if ( QCoreApplication::instance() != 0 ) {
        const QString appExecutableDir = QCoreApplication::instance()->applicationDirPath();
        if ( !executableDirs.contains( appExecutableDir ) ) {
          executableDirs << appExecutableDir;
        }
    }

    executableDirs += searchPath;

#if defined(Q_OS_MAC) //krazy:exclude=cpp
    executableDirs += QLatin1String(AKONADIBUNDLEPATH);
#endif
    qWarning( ) << "search paths: " << executableDirs;

    instance()->mExecutableDirs = executableDirs;
  }

  QStringList::const_iterator pathIt    = instance()->mExecutableDirs.constBegin();
  QStringList::const_iterator pathEndIt = instance()->mExecutableDirs.constEnd();
  for ( ; pathIt != pathEndIt; ++pathIt ) {
    QStringList fullPathList = alternateExecPaths(*pathIt + QLatin1Char( '/' ) + relPath );

    QStringList::const_iterator it    = fullPathList.constBegin();
    QStringList::const_iterator endIt = fullPathList.constEnd();
    for ( ; it != endIt; ++it ) {
      const QFileInfo fileInfo( *it );

      // resolve symlinks, happens eg. with Maemo optify
      if ( fileInfo.canonicalFilePath().isEmpty() )
        continue;
      const QFileInfo canonicalFileInfo( fileInfo.canonicalFilePath() );

      if ( canonicalFileInfo.exists() && canonicalFileInfo.isFile() && canonicalFileInfo.isExecutable() ) {
        return *it;
      }
    }
  }

  return QString();
}

QString XdgBaseDirs::findResourceDir( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QStringList XdgBaseDirs::findAllResourceDirs( const char *resource, const QString &relPath )
{
  QStringList resultList;

  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    resultList << fileInfo.absoluteFilePath();
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.constBegin();
  QStringList::const_iterator endIt = pathList.constEnd();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      resultList << fileInfo.absoluteFilePath();
    }
  }

  return resultList;
}

QString XdgBaseDirs::saveDir( const char *resource, const QString &relPath )
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() ) {
    if ( fileInfo.isDir() ) {
      return fullPath;
    } else {
      qWarning() << "XdgBaseDirs::saveDir: '" << fileInfo.absoluteFilePath()
                 << "' exists but is not a directory";
    }
  } else {
    if ( !QDir::home().mkpath( fileInfo.absoluteFilePath() ) ) {
      qWarning() << "XdgBaseDirs::saveDir: failed to create directory '"
                 << fileInfo.absoluteFilePath() << "'";
    } else {
      return fullPath;
    }
  }

  return QString();
}

QString XdgBaseDirs::akonadiServerConfigFile( FileAccessMode openMode )
{
  return akonadiConfigFile( QLatin1String( "akonadiserverrc" ), openMode );
}

QString XdgBaseDirs::akonadiConnectionConfigFile( FileAccessMode openMode )
{
  return akonadiConfigFile( QLatin1String( "akonadiconnectionrc" ), openMode );
}

QString XdgBaseDirs::akonadiConfigFile( const QString &file, FileAccessMode openMode )
{
  const QString akonadiDir = QLatin1String( "akonadi" );

  QString savePath = saveDir( "config", akonadiDir ) + QLatin1Char( '/' ) + file;

  if ( openMode == WriteOnly ) return savePath;

  QString path = findResourceFile( "config", akonadiDir + QLatin1Char( '/' ) + file );

  if ( path.isEmpty() ) {
    return savePath;
  } else if ( openMode == ReadOnly || path == savePath ) {
    return path;
  }

  // file found in system paths and mode is ReadWrite, thus
  // we copy to the home path location and return this path
  QFile systemFile( path );

  systemFile.copy( savePath );

  return savePath;
}

QString XdgBaseDirsSingleton::homePath( const char *variable, const char *defaultSubDir )
{
  const QByteArray env = qgetenv( variable );

  QString xdgPath;
  if ( env.isEmpty() ) {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QLatin1String( defaultSubDir );
#if defined(Q_OS_WIN) //krazy:exclude=cpp
  } else if ( QDir::isAbsolutePath( QString::fromLocal8Bit( env ) ) ) {
#else
  } else if ( env.startsWith( '/' ) ) {
#endif
    xdgPath = QString::fromLocal8Bit( env );
  } else {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QString::fromLocal8Bit( env );
  }

  return xdgPath;
}

QStringList XdgBaseDirsSingleton::systemPathList( const char *variable, const char *defaultDirList )
{
  const QByteArray env = qgetenv( variable );

  QString xdgDirList;
  if ( env.isEmpty() ) {
    xdgDirList = QLatin1String( defaultDirList );
  } else {
    xdgDirList = QString::fromLocal8Bit( env );
  }

  return splitPathList( xdgDirList );
}
<|endoftext|>


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

#include "xdgbasedirs.h"

#include "akonadi-prefix.h" // for prefix defines

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

#include <cstdlib>

static QStringList alternateExecPaths( const QString& path )
{
  QStringList pathList;

  pathList << path;

#if defined(Q_OS_WIN)
  pathList << path + QLatin1String( ".exe" );
#elif defined(Q_OS_MAC)
  pathList << path + QLatin1String( ".app/Contents/MacOS/" ) + path.section( QLatin1Char( '/' ), -1 );
#endif

  return pathList;
}

namespace Akonadi {

class XdgBaseDirsPrivate
{
  public:
    XdgBaseDirsPrivate() {}

    ~XdgBaseDirsPrivate() {}

    QString homePath( const char *variable, const char *defaultSubDir );

    QStringList systemPathList( const char *variable, const char *defaultDirList );

  public:
    QString mConfigHome;
    QString mDataHome;

    QStringList mConfigDirs;
    QStringList mDataDirs;
    QStringList mExecutableDirs;
};

}

using namespace Akonadi;

XdgBaseDirs::XdgBaseDirs() : d( new XdgBaseDirsPrivate() )
{
}

XdgBaseDirs::~XdgBaseDirs()
{
  delete d;
}

QString XdgBaseDirs::homePath( const char *resource ) const
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( d->mDataHome.isEmpty() ) {
      d->mDataHome = d->homePath( "XDG_DATA_HOME", ".local/share" );
    }
    return d->mDataHome;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( d->mConfigHome.isEmpty() ) {
      d->mConfigHome = d->homePath( "XDG_CONFIG_HOME", ".config" );
    }
    return d->mConfigHome;
  }

  return QString();
}

QStringList XdgBaseDirs::systemPathList( const char *resource ) const
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( d->mDataDirs.isEmpty() ) {
      d->mDataDirs = d->systemPathList( "XDG_DATA_DIRS", "/usr/local/share:/usr/share" );

      QString prefixDataDir = QLatin1String( AKONADIDATA );
      if ( !d->mDataDirs.contains( prefixDataDir ) ) {
        d->mDataDirs << prefixDataDir;
      }
    }
    return d->mDataDirs;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( d->mConfigDirs.isEmpty() ) {
      d->mConfigDirs = d->systemPathList( "XDG_CONFIG_DIRS", "/etc/xdg" );

      QString prefixConfigDir = QLatin1String( AKONADICONFIG );
      if ( !d->mConfigDirs.contains( prefixConfigDir ) ) {
        d->mConfigDirs << prefixConfigDir;
      }
    }
    return d->mConfigDirs;
  }

  return QStringList();
}

QString XdgBaseDirs::findResourceFile( const char *resource, const QString &relPath ) const
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.begin();
  QStringList::const_iterator endIt = pathList.end();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QString XdgBaseDirs::findExecutableFile( const QString &relPath ) const
{
  if ( d->mExecutableDirs.isEmpty() ) {
    d->mExecutableDirs = d->systemPathList( "PATH", "/usr/local/bin:/usr/bin" );

    QString prefixExecutableDir = QLatin1String( AKONADIPREFIX "/bin" );
    if ( !d->mExecutableDirs.contains( prefixExecutableDir ) ) {
      d->mExecutableDirs << prefixExecutableDir;
    }
  }

  QStringList::const_iterator pathIt    = d->mExecutableDirs.begin();
  QStringList::const_iterator pathEndIt = d->mExecutableDirs.end();
  for ( ; pathIt != pathEndIt; ++pathIt ) {
    QStringList fullPathList = alternateExecPaths(*pathIt + QLatin1Char( '/' ) + relPath );

    QStringList::const_iterator it    = fullPathList.begin();
    QStringList::const_iterator endIt = fullPathList.end();
    for ( ; it != endIt; ++it ) {
      QFileInfo fileInfo(*it);

      if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable() ) {
        return *it;
      }
    }
  }

  return QString();
}

QString XdgBaseDirs::findResourceDir( const char *resource, const QString &relPath ) const
{
  QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.begin();
  QStringList::const_iterator endIt = pathList.end();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QStringList XdgBaseDirs::findAllResourceDirs( const char *resource, const QString &relPath ) const
{
  QStringList resultList;

  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    resultList << fileInfo.absoluteFilePath();
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.begin();
  QStringList::const_iterator endIt = pathList.end();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      resultList << fileInfo.absoluteFilePath();
    }
  }

  return resultList;
}

QString XdgBaseDirs::saveDir( const char *resource, const QString &relPath ) const
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() ) {
    if ( fileInfo.isDir() ) {
      return fullPath;
    } else {
      qWarning() << "XdgBaseDirs::saveDir: '" << fileInfo.absoluteFilePath()
                 << "' exists but is not a directory";
    }
  } else {
    if ( !QDir::home().mkpath( fileInfo.absoluteFilePath() ) ) {
      qWarning() << "XdgBaseDirs::saveDir: failed to create directory '"
                 << fileInfo.absoluteFilePath() << "'";
    } else {
      return fullPath;
    }
  }

  return QString();
}

QString XdgBaseDirs::akonadiServerConfigFile( FileAccessMode openMode ) const
{
  return akonadiConfigFile( QLatin1String( "akonadiserverrc" ), openMode );
}

QString XdgBaseDirs::akonadiConnectionConfigFile( FileAccessMode openMode ) const
{
  return akonadiConfigFile( QLatin1String( "akonadiconnectionrc" ), openMode );
}

QString XdgBaseDirs::akonadiConfigFile( const QString &file, FileAccessMode openMode ) const
{
  const QString akonadiDir = QLatin1String( "akonadi" );

  QString savePath = saveDir( "config", akonadiDir ) + QLatin1Char( '/' ) + file;

  if ( openMode == WriteOnly ) return savePath;

  QString path = findResourceFile( "config", akonadiDir + QLatin1Char( '/' ) + file );

  if ( path.isEmpty() ) {
    return savePath;
  } else if ( openMode == ReadOnly || path == savePath ) {
    return path;
  }

  // file found in system paths and mode is ReadWrite, thus
  // we copy to the home path location and return this path
  QFile systemFile( path );

  systemFile.copy( savePath );

  return savePath;
}

QString XdgBaseDirsPrivate::homePath( const char *variable, const char *defaultSubDir )
{
  char *env = std::getenv( variable );

  QString xdgPath;
  if ( env == 0 || *env == '\0' ) {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QLatin1String( defaultSubDir );
  } else if ( *env == '/' ) {
    xdgPath = QString::fromLocal8Bit( env );
  } else {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QString::fromLocal8Bit( env );
  }

  return xdgPath;
}

QStringList XdgBaseDirsPrivate::systemPathList( const char *variable, const char *defaultDirList )
{
  char *env = std::getenv( variable );

  QString xdgDirList;
  if ( env == 0 || *env == '\0' ) {
    xdgDirList = QLatin1String( defaultDirList );
  } else {
    xdgDirList = QString::fromLocal8Bit( env );
  }

  return xdgDirList.split( QLatin1Char( ':' ) );
}
<commit_msg>Improve re-entrance behavior by writing only the end result to the shared member<commit_after>/***************************************************************************
 *   Copyright (C) 2007 by Kevin Krammer <kevin.krammer@gmx.at>            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/

#include "xdgbasedirs.h"

#include "akonadi-prefix.h" // for prefix defines

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

#include <cstdlib>

static QStringList alternateExecPaths( const QString& path )
{
  QStringList pathList;

  pathList << path;

#if defined(Q_OS_WIN)
  pathList << path + QLatin1String( ".exe" );
#elif defined(Q_OS_MAC)
  pathList << path + QLatin1String( ".app/Contents/MacOS/" ) + path.section( QLatin1Char( '/' ), -1 );
#endif

  return pathList;
}

namespace Akonadi {

class XdgBaseDirsPrivate
{
  public:
    XdgBaseDirsPrivate() {}

    ~XdgBaseDirsPrivate() {}

    QString homePath( const char *variable, const char *defaultSubDir );

    QStringList systemPathList( const char *variable, const char *defaultDirList );

  public:
    QString mConfigHome;
    QString mDataHome;

    QStringList mConfigDirs;
    QStringList mDataDirs;
    QStringList mExecutableDirs;
};

}

using namespace Akonadi;

XdgBaseDirs::XdgBaseDirs() : d( new XdgBaseDirsPrivate() )
{
}

XdgBaseDirs::~XdgBaseDirs()
{
  delete d;
}

QString XdgBaseDirs::homePath( const char *resource ) const
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( d->mDataHome.isEmpty() ) {
      d->mDataHome = d->homePath( "XDG_DATA_HOME", ".local/share" );
    }
    return d->mDataHome;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( d->mConfigHome.isEmpty() ) {
      d->mConfigHome = d->homePath( "XDG_CONFIG_HOME", ".config" );
    }
    return d->mConfigHome;
  }

  return QString();
}

QStringList XdgBaseDirs::systemPathList( const char *resource ) const
{
  if ( qstrncmp( "data", resource, 4 ) == 0 ) {
    if ( d->mDataDirs.isEmpty() ) {
      QStringList dataDirs = d->systemPathList( "XDG_DATA_DIRS", "/usr/local/share:/usr/share" );

      const QString prefixDataDir = QLatin1String( AKONADIDATA );
      if ( !dataDirs.contains( prefixDataDir ) ) {
        dataDirs << prefixDataDir;
      }

      d->mDataDirs = dataDirs;
    }
    return d->mDataDirs;
  } else if ( qstrncmp( "config", resource, 6 ) == 0 ) {
    if ( d->mConfigDirs.isEmpty() ) {
      QStringList configDirs = d->systemPathList( "XDG_CONFIG_DIRS", "/etc/xdg" );

      const QString prefixConfigDir = QLatin1String( AKONADICONFIG );
      if ( !configDirs.contains( prefixConfigDir ) ) {
        configDirs << prefixConfigDir;
      }

      d->mConfigDirs = configDirs;
    }
    return d->mConfigDirs;
  }

  return QStringList();
}

QString XdgBaseDirs::findResourceFile( const char *resource, const QString &relPath ) const
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.begin();
  QStringList::const_iterator endIt = pathList.end();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QString XdgBaseDirs::findExecutableFile( const QString &relPath ) const
{
  if ( d->mExecutableDirs.isEmpty() ) {
    QStringList executableDirs = d->systemPathList( "PATH", "/usr/local/bin:/usr/bin" );

    const QString prefixExecutableDir = QLatin1String( AKONADIPREFIX "/bin" );
    if ( !executableDirs.contains( prefixExecutableDir ) ) {
      executableDirs << prefixExecutableDir;
    }

    d->mExecutableDirs = executableDirs;
  }

  QStringList::const_iterator pathIt    = d->mExecutableDirs.begin();
  QStringList::const_iterator pathEndIt = d->mExecutableDirs.end();
  for ( ; pathIt != pathEndIt; ++pathIt ) {
    QStringList fullPathList = alternateExecPaths(*pathIt + QLatin1Char( '/' ) + relPath );

    QStringList::const_iterator it    = fullPathList.begin();
    QStringList::const_iterator endIt = fullPathList.end();
    for ( ; it != endIt; ++it ) {
      QFileInfo fileInfo(*it);

      if ( fileInfo.exists() && fileInfo.isFile() && fileInfo.isExecutable() ) {
        return *it;
      }
    }
  }

  return QString();
}

QString XdgBaseDirs::findResourceDir( const char *resource, const QString &relPath ) const
{
  QString fullPath = homePath( resource ) + QLatin1Char( '/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    return fullPath;
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.begin();
  QStringList::const_iterator endIt = pathList.end();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      return fileInfo.absoluteFilePath();
    }
  }

  return QString();
}

QStringList XdgBaseDirs::findAllResourceDirs( const char *resource, const QString &relPath ) const
{
  QStringList resultList;

  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
    resultList << fileInfo.absoluteFilePath();
  }

  QStringList pathList = systemPathList( resource );

  QStringList::const_iterator it    = pathList.begin();
  QStringList::const_iterator endIt = pathList.end();
  for ( ; it != endIt; ++it ) {
    fileInfo = QFileInfo( *it + QLatin1Char('/' ) + relPath );
    if ( fileInfo.exists() && fileInfo.isDir() && fileInfo.isReadable() ) {
      resultList << fileInfo.absoluteFilePath();
    }
  }

  return resultList;
}

QString XdgBaseDirs::saveDir( const char *resource, const QString &relPath ) const
{
  QString fullPath = homePath( resource ) + QLatin1Char('/' ) + relPath;

  QFileInfo fileInfo( fullPath );
  if ( fileInfo.exists() ) {
    if ( fileInfo.isDir() ) {
      return fullPath;
    } else {
      qWarning() << "XdgBaseDirs::saveDir: '" << fileInfo.absoluteFilePath()
                 << "' exists but is not a directory";
    }
  } else {
    if ( !QDir::home().mkpath( fileInfo.absoluteFilePath() ) ) {
      qWarning() << "XdgBaseDirs::saveDir: failed to create directory '"
                 << fileInfo.absoluteFilePath() << "'";
    } else {
      return fullPath;
    }
  }

  return QString();
}

QString XdgBaseDirs::akonadiServerConfigFile( FileAccessMode openMode ) const
{
  return akonadiConfigFile( QLatin1String( "akonadiserverrc" ), openMode );
}

QString XdgBaseDirs::akonadiConnectionConfigFile( FileAccessMode openMode ) const
{
  return akonadiConfigFile( QLatin1String( "akonadiconnectionrc" ), openMode );
}

QString XdgBaseDirs::akonadiConfigFile( const QString &file, FileAccessMode openMode ) const
{
  const QString akonadiDir = QLatin1String( "akonadi" );

  QString savePath = saveDir( "config", akonadiDir ) + QLatin1Char( '/' ) + file;

  if ( openMode == WriteOnly ) return savePath;

  QString path = findResourceFile( "config", akonadiDir + QLatin1Char( '/' ) + file );

  if ( path.isEmpty() ) {
    return savePath;
  } else if ( openMode == ReadOnly || path == savePath ) {
    return path;
  }

  // file found in system paths and mode is ReadWrite, thus
  // we copy to the home path location and return this path
  QFile systemFile( path );

  systemFile.copy( savePath );

  return savePath;
}

QString XdgBaseDirsPrivate::homePath( const char *variable, const char *defaultSubDir )
{
  char *env = std::getenv( variable );

  QString xdgPath;
  if ( env == 0 || *env == '\0' ) {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QLatin1String( defaultSubDir );
  } else if ( *env == '/' ) {
    xdgPath = QString::fromLocal8Bit( env );
  } else {
    xdgPath = QDir::homePath() + QLatin1Char( '/' ) + QString::fromLocal8Bit( env );
  }

  return xdgPath;
}

QStringList XdgBaseDirsPrivate::systemPathList( const char *variable, const char *defaultDirList )
{
  char *env = std::getenv( variable );

  QString xdgDirList;
  if ( env == 0 || *env == '\0' ) {
    xdgDirList = QLatin1String( defaultDirList );
  } else {
    xdgDirList = QString::fromLocal8Bit( env );
  }

  return xdgDirList.split( QLatin1Char( ':' ) );
}
<|endoftext|>


<commit_before>#include "ghost/config.h"
#include "ghost/types.h"
#include "ghost/densemat.h"
#include "ghost/util.h"
#include "ghost/math.h"
#include "ghost/tsmttsm.h"
#include "ghost/tsmttsm_gen.h"
#include "ghost/tsmttsm_avx_gen.h"

#include <map>

using namespace std;

static bool operator<(const ghost_tsmttsm_parameters_t &a, const ghost_tsmttsm_parameters_t &b)
{
    return ghost_hash(a.dt,a.wcols,ghost_hash(a.vcols,a.impl,0)) < ghost_hash(b.dt,b.wcols,ghost_hash(b.vcols,b.impl,0));
}

static map<ghost_tsmttsm_parameters_t, ghost_tsmttsm_kernel_t> ghost_tsmttsm_kernels;

ghost_error_t ghost_tsmttsm_valid(ghost_densemat_t *x, ghost_densemat_t *v, const char * transv,
ghost_densemat_t *w, const char *transw, void *alpha, void *beta, int reduce, int printerror)
{
    if (w->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("w must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("v must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (x->traits.storage != GHOST_DENSEMAT_COLMAJOR) {
        if (printerror) {
            ERROR_LOG("x must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.datatype != w->traits.datatype || v->traits.datatype != x->traits.datatype) {
        if (printerror) {
            ERROR_LOG("Different data types!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.flags & GHOST_DENSEMAT_SCATTERED || w->traits.flags & GHOST_DENSEMAT_SCATTERED || x->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        if (printerror) {
            ERROR_LOG("Scattered densemats not supported!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (reduce != GHOST_GEMM_ALL_REDUCE) {
        if (printerror) {
            ERROR_LOG("Only Allreduce supported currently!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (!strncasecmp(transv,"N",1)) {
        if (printerror) {
            ERROR_LOG("v must be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (strncasecmp(transw,"N",1)) {
        if (printerror) {
            ERROR_LOG("w must not be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    UNUSED(alpha);
    UNUSED(beta);

    return GHOST_SUCCESS;
}

ghost_error_t ghost_tsmttsm(ghost_densemat_t *x, ghost_densemat_t *v, ghost_densemat_t *w, void *alpha, void *beta,int reduce,int conjv)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error_t ret;

    if ((ret = ghost_tsmttsm_valid(x,v,"T",w,"N",alpha,beta,reduce,1)) != GHOST_SUCCESS) {
        return ret;
    }

    if (ghost_tsmttsm_kernels.empty()) {
#include "tsmttsm.def"
#include "tsmttsm_avx.def"
    }

    ghost_tsmttsm_parameters_t p;
    ghost_tsmttsm_kernel_t kernel = NULL;

#ifdef GHOST_HAVE_MIC
    p.impl = GHOST_IMPLEMENTATION_MIC;
#elif defined(GHOST_HAVE_AVX)
    p.impl = GHOST_IMPLEMENTATION_AVX;
#elif defined(GHOST_HAVE_SSE)
    p.impl = GHOST_IMPLEMENTATION_SSE;
#endif

    p.dt = x->traits.datatype;

    p.vcols = v->traits.ncols;
    p.wcols = w->traits.ncols;
    if (p.vcols == 2 || p.wcols == 2) {
        p.impl = GHOST_IMPLEMENTATION_SSE;
    }
    if (p.vcols == 1 || p.wcols == 1) {
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }
    if (p.vcols % 4 || p.wcols % 4) {
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with non-padded blocks");
        p.wcols = w->traits.ncols;
        if (p.vcols == 2 || p.wcols == 2) {
            p.impl = GHOST_IMPLEMENTATION_SSE;
        }
        if (p.vcols == 1 || p.wcols == 1) {
            p.impl = GHOST_IMPLEMENTATION_PLAIN;
        }
        if (p.vcols % 4 || p.wcols % 4) {
            p.impl = GHOST_IMPLEMENTATION_PLAIN;
        }
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try plain implementation");
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }
    kernel = ghost_tsmttsm_kernels[p];

    if (!kernel) {
        INFO_LOG("Could not find TSMTTSM kernel with %d %d %d. Fallback to GEMM",p.dt,p.wcols,p.vcols);
        return GHOST_ERR_INVALID_ARG;

            //return ghost_gemm(x,v,"T",w,"N",alpha,beta,GHOST_GEMM_ALL_REDUCE,GHOST_GEMM_NOT_SPECIAL);
    }

    ret = kernel(x,v,w,alpha,beta,conjv);

#ifdef GHOST_HAVE_INSTR_TIMING
    ghost_gemm_perf_args_t tsmttsm_perfargs;
    tsmttsm_perfargs.xcols = p.wcols;
    tsmttsm_perfargs.vcols = p.vcols;
    tsmttsm_perfargs.vrows = v->context->gnrows;
    tsmttsm_perfargs.dt = x->traits.datatype;
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GFs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GF/s");
#endif

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);

    return ret;
}

<commit_msg>better selection of TSMTTSM kernel<commit_after>#include "ghost/config.h"
#include "ghost/types.h"
#include "ghost/densemat.h"
#include "ghost/util.h"
#include "ghost/math.h"
#include "ghost/tsmttsm.h"
#include "ghost/tsmttsm_gen.h"
#include "ghost/tsmttsm_avx_gen.h"

#include <map>

using namespace std;

static bool operator<(const ghost_tsmttsm_parameters_t &a, const ghost_tsmttsm_parameters_t &b)
{
    return ghost_hash(a.dt,a.wcols,ghost_hash(a.vcols,a.impl,0)) < ghost_hash(b.dt,b.wcols,ghost_hash(b.vcols,b.impl,0));
}

static map<ghost_tsmttsm_parameters_t, ghost_tsmttsm_kernel_t> ghost_tsmttsm_kernels;

ghost_error_t ghost_tsmttsm_valid(ghost_densemat_t *x, ghost_densemat_t *v, const char * transv,
ghost_densemat_t *w, const char *transw, void *alpha, void *beta, int reduce, int printerror)
{
    if (w->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("w must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("v must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (x->traits.storage != GHOST_DENSEMAT_COLMAJOR) {
        if (printerror) {
            ERROR_LOG("x must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.datatype != w->traits.datatype || v->traits.datatype != x->traits.datatype) {
        if (printerror) {
            ERROR_LOG("Different data types!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.flags & GHOST_DENSEMAT_SCATTERED || w->traits.flags & GHOST_DENSEMAT_SCATTERED || x->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        if (printerror) {
            ERROR_LOG("Scattered densemats not supported!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (reduce != GHOST_GEMM_ALL_REDUCE) {
        if (printerror) {
            ERROR_LOG("Only Allreduce supported currently!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (!strncasecmp(transv,"N",1)) {
        if (printerror) {
            ERROR_LOG("v must be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (strncasecmp(transw,"N",1)) {
        if (printerror) {
            ERROR_LOG("w must not be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    UNUSED(alpha);
    UNUSED(beta);

    return GHOST_SUCCESS;
}

ghost_error_t ghost_tsmttsm(ghost_densemat_t *x, ghost_densemat_t *v, ghost_densemat_t *w, void *alpha, void *beta,int reduce,int conjv)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error_t ret;

    if ((ret = ghost_tsmttsm_valid(x,v,"T",w,"N",alpha,beta,reduce,1)) != GHOST_SUCCESS) {
        return ret;
    }

    if (ghost_tsmttsm_kernels.empty()) {
#include "tsmttsm.def"
#include "tsmttsm_avx.def"
    }

    ghost_tsmttsm_parameters_t p;
    ghost_tsmttsm_kernel_t kernel = NULL;

#ifdef GHOST_HAVE_MIC
    p.impl = GHOST_IMPLEMENTATION_MIC;
#elif defined(GHOST_HAVE_AVX)
    p.impl = GHOST_IMPLEMENTATION_AVX;
#elif defined(GHOST_HAVE_SSE)
    p.impl = GHOST_IMPLEMENTATION_SSE;
#endif

    p.dt = x->traits.datatype;

    p.vcols = v->traits.ncols;
    p.wcols = w->traits.ncols;
    kernel = ghost_tsmttsm_kernels[p];

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kernels[p];
    }

    if (!kernel) {
        PERFWARNING_LOG("Try plain implementation");
        p.impl = GHOST_IMPLEMENTATION_PLAIN;
    }
    kernel = ghost_tsmttsm_kernels[p];

    if (!kernel) {
        INFO_LOG("Could not find TSMTTSM kernel with %d %d %d. Fallback to GEMM",p.dt,p.wcols,p.vcols);
        return GHOST_ERR_INVALID_ARG;

            //return ghost_gemm(x,v,"T",w,"N",alpha,beta,GHOST_GEMM_ALL_REDUCE,GHOST_GEMM_NOT_SPECIAL);
    }

    ret = kernel(x,v,w,alpha,beta,conjv);

#ifdef GHOST_HAVE_INSTR_TIMING
    ghost_gemm_perf_args_t tsmttsm_perfargs;
    tsmttsm_perfargs.xcols = p.wcols;
    tsmttsm_perfargs.vcols = p.vcols;
    tsmttsm_perfargs.vrows = v->context->gnrows;
    tsmttsm_perfargs.dt = x->traits.datatype;
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GFs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GF/s");
#endif

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);

    return ret;
}

<|endoftext|>


<commit_before>#include "twister.h"

const unsigned CYCLE = 0x100;

const unsigned C_TRANS_ = 0xff;
int block_units[][0x10] = {
	0x74, 0x63, 0x69, 0x67, 0x72, 0x68, 0x6e, 0x6c, 0x61, 0x67, 0x74, 0x6c, 0x69, 0x73, 0x61, 0x61, 0x6f, 0x6d, 0x6f, 0x72, 0x6e, 0x72, 0x69, 0x6d, 0x6e, 0x6e, 0x65, 0x74, 0x72, 0x6e, 0x6b, 0x73, 0x61, 0x6f, 0x65, 0x69, 0x73, 0x64, 0x6c, 0x65, 0x69, 0x6b, 0x68, 0x68, 0x68, 0x65, 0x72, 0x64, 0x66, 0x74, 0x61, 0x73, 0x6f, 0x69, 0x65, 0x74, 0x69, 0x68, 0x6e, 0x65, 0x62, 0x74, 0x6b, 0x65
  };
int triad_units[][0x03] = {
	0x74, 0x68, 0x65, 0x74, 0x68, 0x61, 0x65, 0x74, 0x68, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x65, 0x68, 0x61, 0x74, 0x68, 0x69, 0x73
};
const int transition_seq[] = { 0xce, 0xab, 0xdf, 0xcf, 0xee,
                               0xcf, 0xad, 0xdf, 0xff, 0xce,
                               0x32, 0x40, 0xd3, 0x27, 0x82,
                               0xda, 0xee, 0xff, 0xfc, 0xbf,
                               0x1c, 0x90, 0x13, 0x4a, 0xa5,
                               0xe0, 0x21, 0x9f, 0xe1, 0xc6,
                               0xe4, 0x38, 0x1f, 0x60, 0x24,
                               0x0c, 0x35, 0x51, 0x32, 0xcf,
                               0x12, 0x9a, 0x30, 0x44, 0x72,
                               0x04, 0x1c, 0x52, 0xca, 0xdf,
                               0x12, 0x0b, 0x30, 0xa0, 0x1e,
                               0x03, 0x14, 0x09, 0x73, 0x23,
                               0xf2, 0xca, 0xa2, 0x51, 0xc6,
                               0xcb, 0xbd, 0xba, 0xac, 0xdf,
                               0xdf, 0xde, 0xcd, 0xfd, 0xca };

unsigned reflect(unsigned center, unsigned (*r)(unsigned))
{
  return (*r)(center)^center;
}
unsigned char base(unsigned char a, unsigned char (*s)(unsigned char), int pos)
{
	return (*s)(pos)^a;
}

void transHomExt(vector<unsigned char>& data, unsigned char (*f)(unsigned char), unsigned char (*g)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d)^base(d, g, d);
    }
    data[i] = d;
  }
}
void transHom(vector<unsigned char>& data, unsigned char (*f)(unsigned char), unsigned char (*g)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d)^(*g)(d);
    }
    data[i] = d;
  }
}

void trans(vector<unsigned char>& data, unsigned char (*f)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d);
    }
    data[i] = d;
  }
}

vector<double> f_dist(vector<unsigned char>& in)
{
  vector<double> fdist;
  fdist.resize(256);
  for(unsigned i = 0; i<in.size(); i++)
  {
    fdist[in[i]]++;
  }

  for(unsigned i=0; i<fdist.size(); i++)
  {
    fdist[i] = (fdist[i] / in.size()) * 100;
  }

  return fdist;
}

double s_entropy(vector<double> v)
{
  double entropy = 0;
  double p;

  for(unsigned i = 0; i < v.size(); i++)
  {
    p = v[i] / 100;
    if (p == 0) continue;
    entropy += p * std::log(p) / std::log(2);
  }
  return -entropy;
}
void rms(const string& s, string& r)
{
  for(unsigned int i=0; i<s.size(); i++)
  {
    if(::isspace(s[i])) continue;
    r+= s[i];
  }
}

double sw(double weight, int i, int j, int (*inv)(int, int))
{
  return weight*(*inv)(i, j);
}
void hPerm(int s, int n, void (*p)(int), void (*inv)(int, int))
{
  if(s == 1)
  {
    (*p)(n);
    return;
  }
  for(int i=0; i< s; i++)
  {
    hPerm(s-1, n, p, inv);
    if(s%2 == 1)
      (*inv)(0, s-1);
    else
      (*inv)(i, s-1);
  }
}

double ic(const string& t)
{
  string text; rms(t, text);
  vector<double> freq(256,0);
  for(unsigned int i=0; i<text.size(); i++)
  {
    if(text[i] == ' ') continue;
    freq[text[i]] ++;
  }
  double sum=0;
  for(unsigned int i=0; i<freq.size(); i++)
  {
    if(freq[i] != 0)
    {
      double c = freq[i];
      if(c != 0)
        sum += c * (c - 1);
    }
  }
  double ic = 26 * sum / (text.size() * (text.size() - 1));
  return ic;
}
<commit_msg>test seq, entry point<commit_after>#include "twister.h"

const unsigned CYCLE = 0x100;

const unsigned C_TRANS_ = 0xff;
int block_units[][0x10] = {
	0x74, 0x63, 0x69, 0x67, 0x72, 0x68, 0x6e, 0x6c, 0x61, 0x67, 0x74, 0x6c, 0x69, 0x73, 0x61, 0x61, 0x6f, 0x6d, 0x6f, 0x72, 0x6e, 0x72, 0x69, 0x6d, 0x6e, 0x6e, 0x65, 0x74, 0x72, 0x6e, 0x6b, 0x73, 0x61, 0x6f, 0x65, 0x69, 0x73, 0x64, 0x6c, 0x65, 0x69, 0x6b, 0x68, 0x68, 0x68, 0x65, 0x72, 0x64, 0x66, 0x74, 0x61, 0x73, 0x6f, 0x69, 0x65, 0x74, 0x69, 0x68, 0x6e, 0x65, 0x62, 0x74, 0x6b, 0x65
  };
int triad_units[][0x03] = {
	0x74, 0x68, 0x65, 0x74, 0x68, 0x61, 0x65, 0x74, 0x68, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x65, 0x68, 0x61, 0x74, 0x68, 0x69, 0x73
};
const int transition_seq[] = { 0xce, 0xab, 0xdf, 0xcf, 0xee,
                               0xcf, 0xad, 0xdf, 0xff, 0xce,
                               0x32, 0x40, 0xd3, 0x27, 0x82,
                               0xda, 0xee, 0xff, 0xfc, 0xbf,
                               0x1c, 0x90, 0x13, 0x4a, 0xa5,
                               0xe0, 0x21, 0x9f, 0xe1, 0xc6,
                               0xe4, 0x38, 0x1f, 0x60, 0x24,
                               0x0c, 0x35, 0x51, 0x32, 0xcf,
                               0x12, 0x9a, 0x30, 0x44, 0x72,
                               0x04, 0x1c, 0x52, 0xca, 0xdf,
                               0x12, 0x0b, 0x30, 0xa0, 0x1e,
                               0x03, 0x14, 0x09, 0x73, 0x23,
                               0xf2, 0xca, 0xa2, 0x51, 0xc6,
                               0xcb, 0xbd, 0xba, 0xac, 0xdf,
			       0xdf, 0xde, 0xcd, 0xfd, 0xca };

int ENTRY_LINK__ = 0x05;

unsigned reflect(unsigned center, unsigned (*r)(unsigned))
{
  return (*r)(center)^center;
}
unsigned char base(unsigned char a, unsigned char (*s)(unsigned char), int pos)
{
	return (*s)(pos)^a;
}

void transHomExt(vector<unsigned char>& data, unsigned char (*f)(unsigned char), unsigned char (*g)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d)^base(d, g, d);
    }
    data[i] = d;
  }
}
void transHom(vector<unsigned char>& data, unsigned char (*f)(unsigned char), unsigned char (*g)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d)^(*g)(d);
    }
    data[i] = d;
  }
}

void trans(vector<unsigned char>& data, unsigned char (*f)(unsigned char))
{
  for(unsigned i = 0; i<data.size(); i++)
  {
    unsigned char d = data[i];
    for(unsigned j=0; j<CYCLE; j++)
    {
      d = (*f)(d);
    }
    data[i] = d;
  }
}

vector<double> f_dist(vector<unsigned char>& in)
{
  vector<double> fdist;
  fdist.resize(256);
  for(unsigned i = 0; i<in.size(); i++)
  {
    fdist[in[i]]++;
  }

  for(unsigned i=0; i<fdist.size(); i++)
  {
    fdist[i] = (fdist[i] / in.size()) * 100;
  }

  return fdist;
}

double s_entropy(vector<double> v)
{
  double entropy = 0;
  double p;

  for(unsigned i = 0; i < v.size(); i++)
  {
    p = v[i] / 100;
    if (p == 0) continue;
    entropy += p * std::log(p) / std::log(2);
  }
  return -entropy;
}
void rms(const string& s, string& r)
{
  for(unsigned int i=0; i<s.size(); i++)
  {
    if(::isspace(s[i])) continue;
    r+= s[i];
  }
}

double sw(double weight, int i, int j, int (*inv)(int, int))
{
  return weight*(*inv)(i, j);
}
void hPerm(int s, int n, void (*p)(int), void (*inv)(int, int))
{
  if(s == 1)
  {
    (*p)(n);
    return;
  }
  for(int i=0; i< s; i++)
  {
    hPerm(s-1, n, p, inv);
    if(s%2 == 1)
      (*inv)(0, s-1);
    else
      (*inv)(i, s-1);
  }
}

double ic(const string& t)
{
  string text; rms(t, text);
  vector<double> freq(256,0);
  for(unsigned int i=0; i<text.size(); i++)
  {
    if(text[i] == ' ') continue;
    freq[text[i]] ++;
  }
  double sum=0;
  for(unsigned int i=0; i<freq.size(); i++)
  {
    if(freq[i] != 0)
    {
      double c = freq[i];
      if(c != 0)
        sum += c * (c - 1);
    }
  }
  double ic = 26 * sum / (text.size() * (text.size() - 1));
  return ic;
}

void switchIO(unsigned char (*p)(unsigned char, unsigned char))
{
  //test seq
  (*p)(transition_seq[ENTRY_LINK__], 0x10);
}
<|endoftext|>