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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperListViewParameter.h"

namespace otb
{
namespace Wrapper
{

ListViewParameter::ListViewParameter()
  : m_ChoiceList(),
    m_CurrentChoice(0),
    m_SelectedItems(),
    m_SelectedKeys(),
    m_SelectedNames(),
    m_SingleSelection(false)
{
}

ListViewParameter::~ListViewParameter()
{
}

void
ListViewParameter::AddChoice( std::string choicekey, std::string choiceName )
{
  ListViewChoice choice;
  choice.m_Key = choicekey;
  choice.m_Name = choiceName;
  m_ChoiceList.push_back(choice);
}

std::string
ListViewParameter::GetChoiceKey( int i )
{
  if (m_ChoiceList.empty())
  {
    return "";
  }
  else
  {
    return m_ChoiceList[i].m_Key;
  }
}

std::vector<std::string>
ListViewParameter::GetChoiceKeys( )
{
  std::vector<std::string> ret;
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    ret.push_back(it->m_Key);
    }

  return ret;
}

std::string
ListViewParameter::GetChoiceName( int i )
{
  if (m_ChoiceList.empty())
  {
    return "";
  }
  else
  {
    return m_ChoiceList[i].m_Name;
  }
}

std::vector<std::string>
ListViewParameter::GetChoiceNames( )
{
  std::vector<std::string> ret;
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    ret.push_back(it->m_Name);
    }
  return ret;
}

unsigned int
ListViewParameter::GetNbChoices( void )
{
  return m_ChoiceList.size();
}

void
ListViewParameter::SetValue(unsigned int v)
{
  m_CurrentChoice = v;
  SetActive(true);
  // Call Modified();
  this->Modified();
}

void
ListViewParameter::SetValue(std::string choiceKey)
{
  ChoiceList::iterator it = m_ChoiceList.begin();

  unsigned int i = 0;
  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    if ( it->m_Key == choiceKey )
      {
      SetValue(i);
      return;
      }
    ++i;
    }

  itkExceptionMacro(<< "Cannot find " << choiceKey);
}

unsigned int
ListViewParameter::GetValue()
{
  return m_CurrentChoice;
}

/** Clear choices */
void
ListViewParameter::ClearChoices()
{
  m_ChoiceList.clear();
}

void
ListViewParameter::SetSelectedNames(std::vector<std::string> selectedNames)
{
  std::vector<int> selectedItems;
  std::vector<std::string> names = this->GetChoiceNames();

  if(m_SingleSelection && m_SelectedNames.size() > 1)
    {
    itkExceptionMacro(<<"Single selection mode is on, but there are "<<m_SelectedNames.size()<<" selected items");
    }

  for(unsigned int i=0; i<m_SelectedNames.size(); i++)
    {
    const std::string selectedName = selectedNames[i];
    unsigned int j(0);
      for(; j<names.size(); j++)
      {
      if( names[j] == selectedName )
            {
        selectedItems.push_back(j);
        break;
        }
      }
    // If not found
    if( j==names.size() )
      {
      std::ostringstream oss;
      for( j=0; j<names.size(); j++)
        {
        oss<<names[j];
        if( j < names.size()-1 )
          {
          oss<<", ";
          }
        }
      itkExceptionMacro("Value "<<selectedName<<" not found in the list of choices: "<<oss.str()<<".");
      }
    }
  this->SetSelectedItems(selectedItems);
}

void
ListViewParameter::SetSelectedKeys(std::vector<std::string> selectedKeys)
{
  std::vector<int> selectedItems;
  std::vector<std::string> keys = this->GetChoiceKeys();

if(m_SingleSelection && m_SelectedKeys.size() > 1)
    {
    itkExceptionMacro(<<"Single selection mode is on, but there are "<<m_SelectedKeys.size()<<" selected items");
    }

  for(unsigned int i=0; i<m_SelectedKeys.size(); i++)
    {
    const std::string selectedKey = selectedKeys[i];
    unsigned int j(0);
    std::ostringstream oss;
      for(; j<keys.size(); j++)
      {
      if( keys[j] == selectedKey )
            {
        selectedItems.push_back(j);
        break;
        }
      }
    // If not found
    if( j==keys.size() )
      {
      for( j=0; j<keys.size(); j++)
        {
        oss<<keys[j];
        if( j < keys.size()-1 )
          {
          oss<<", ";
          }
        }
      itkExceptionMacro("Value "<<selectedKey<<" not found in the list of choices: "<<oss.str()<<".");
      }
    }
  this->SetSelectedItems(selectedItems);
}
}
}
<commit_msg>BUG: bad merge on ListViewParameter<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperListViewParameter.h"

namespace otb
{
namespace Wrapper
{

ListViewParameter::ListViewParameter()
  : m_ChoiceList(),
    m_CurrentChoice(0),
    m_SelectedItems(),
    m_SelectedKeys(),
    m_SelectedNames(),
    m_SingleSelection(false)
{
}

ListViewParameter::~ListViewParameter()
{
}

void
ListViewParameter::AddChoice( std::string choicekey, std::string choiceName )
{
  ListViewChoice choice;
  choice.m_Key = choicekey;
  choice.m_Name = choiceName;
  m_ChoiceList.push_back(choice);
}

std::string
ListViewParameter::GetChoiceKey( int i )
{
  if (m_ChoiceList.empty())
  {
    return "";
  }
  else
  {
    return m_ChoiceList[i].m_Key;
  }
}

std::vector<std::string>
ListViewParameter::GetChoiceKeys( )
{
  std::vector<std::string> ret;
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    ret.push_back(it->m_Key);
    }

  return ret;
}

std::string
ListViewParameter::GetChoiceName( int i )
{
  if (m_ChoiceList.empty())
  {
    return "";
  }
  else
  {
    return m_ChoiceList[i].m_Name;
  }
}

std::vector<std::string>
ListViewParameter::GetChoiceNames( )
{
  std::vector<std::string> ret;
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    ret.push_back(it->m_Name);
    }
  return ret;
}

unsigned int
ListViewParameter::GetNbChoices( void )
{
  return m_ChoiceList.size();
}

void
ListViewParameter::SetValue(unsigned int v)
{
  m_CurrentChoice = v;
  SetActive(true);
  // Call Modified();
  this->Modified();
}

void
ListViewParameter::SetValue(std::string choiceKey)
{
  ChoiceList::iterator it = m_ChoiceList.begin();

  unsigned int i = 0;
  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    if ( it->m_Key == choiceKey )
      {
      SetValue(i);
      return;
      }
    ++i;
    }

  itkExceptionMacro(<< "Cannot find " << choiceKey);
}

unsigned int
ListViewParameter::GetValue()
{
  return m_CurrentChoice;
}

/** Clear choices */
void
ListViewParameter::ClearChoices()
{
  m_ChoiceList.clear();
}

void
ListViewParameter::SetSelectedNames(std::vector<std::string> selectedNames)
{
  std::vector<int> selectedItems;
  std::vector<std::string> names = this->GetChoiceNames();

  if(m_SingleSelection && selectedNames.size() > 1)
    {
    itkExceptionMacro(<<"Single selection mode is on, but there are "<<selectedNames.size()<<" selected items");
    }

  for(unsigned int i=0; i<selectedNames.size(); i++)
    {
    const std::string selectedName = selectedNames[i];
    unsigned int j(0);
      for(; j<names.size(); j++)
      {
      if( names[j] == selectedName )
            {
        selectedItems.push_back(j);
        break;
        }
      }
    // If not found
    if( j==names.size() )
      {
      std::ostringstream oss;
      for( j=0; j<names.size(); j++)
        {
        oss<<names[j];
        if( j < names.size()-1 )
          {
          oss<<", ";
          }
        }
      itkExceptionMacro("Value "<<selectedName<<" not found in the list of choices: "<<oss.str()<<".");
      }
    }
  this->SetSelectedItems(selectedItems);
}

void
ListViewParameter::SetSelectedKeys(std::vector<std::string> selectedKeys)
{
  std::vector<int> selectedItems;
  std::vector<std::string> keys = this->GetChoiceKeys();

if(m_SingleSelection && m_SelectedKeys.size() > 1)
    {
    itkExceptionMacro(<<"Single selection mode is on, but there are "<<m_SelectedKeys.size()<<" selected items");
    }

  for(unsigned int i=0; i<m_SelectedKeys.size(); i++)
    {
    const std::string selectedKey = selectedKeys[i];
    unsigned int j(0);
    std::ostringstream oss;
      for(; j<keys.size(); j++)
      {
      if( keys[j] == selectedKey )
            {
        selectedItems.push_back(j);
        break;
        }
      }
    // If not found
    if( j==keys.size() )
      {
      for( j=0; j<keys.size(); j++)
        {
        oss<<keys[j];
        if( j < keys.size()-1 )
          {
          oss<<", ";
          }
        }
      itkExceptionMacro("Value "<<selectedKey<<" not found in the list of choices: "<<oss.str()<<".");
      }
    }
  this->SetSelectedItems(selectedItems);
}
}
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperCommandLineLauncher.h"
#include "otb_tinyxml.h"
#include <vector>

#ifdef OTB_USE_MPI
#include "otbMPIConfig.h"
#endif

const std::string GetChildNodeTextOf(TiXmlElement *parentElement, std::string key);
std::string PrepareExpressionFromXML(std::string filename);
std::vector<std::string> PrepareVectorExpressionFromXML(std::string filename);
std::string CleanWord(const std::string & word);

std::string PrepareExpressionFromXML(std::string filename)
{
  std::string expression;

  if(filename.empty())
    {
    std::cerr <<"Input XML Filename is empty" << std::endl;
    return expression;
    }
  std::string ext = filename.substr(filename.size()-4,filename.size());
  if(ext != ".xml" )
    std::cerr << ext  << " is a wrong extension: Expected .xml " << __FILE__ << std::endl;

  // Open the xml file
  TiXmlDocument doc;

  //Use itksys::SystemTools::FOpen() and close it below because
  //TiXmlDocument::TiXmlFileOpen( ) is not exposed from tinyXML library. Even
  //though its available in the TiXmlDocument::SaveFile().
  FILE* fp =  itksys::SystemTools::Fopen(filename.c_str(), "rb");

  if (!doc.LoadFile(fp , TIXML_ENCODING_UTF8))
    {
    std::cerr << "Can't open file " << filename << std::endl;
    fclose(fp);
    exit(1);

    }

  TiXmlHandle handle(&doc);

  TiXmlElement *n_OTB;
  n_OTB = handle.FirstChild("OTB").Element();

  if(!n_OTB)
  {
    std::string info = "Input XML file " + filename + " is invalid.";
    std::cerr << info  << std::endl;
    fclose(fp);
    exit(1);
  }

  TiXmlElement *n_AppNode   = n_OTB->FirstChildElement("application");

  std::string moduleName;
  moduleName = GetChildNodeTextOf(n_AppNode, "name");
  /*
  AddMetaData("appname", app_Name);

  app_Descr = this_->GetChildNodeTextOf(n_AppNode, "descr");
  AddMetaData("appdescr", app_Descr);

  TiXmlElement* n_Doc    = n_AppNode->FirstChildElement("doc");

  std::string doc_Name, doc_Descr, doc_Author, doc_Limitation, doc_SeeAlso;

  doc_Name = this_->GetChildNodeTextOf(n_Doc, "name");
  AddMetaData("docname", doc_Name);

  doc_Descr = this_->GetChildNodeTextOf(n_Doc, "longdescr");
  AddMetaData("doclongdescr", doc_Descr);

  doc_Author = this_->GetChildNodeTextOf(n_Doc, "authors");
  AddMetaData("docauthors", doc_Author);

  doc_Limitation = this_->GetChildNodeTextOf(n_Doc, "limitations");
  AddMetaData("doclimitations", doc_Limitation);

  doc_SeeAlso = this_->GetChildNodeTextOf(n_Doc, "seealso");
  AddMetaData("docseealso", doc_SeeAlso);
  */

  expression.append(moduleName);

  for( TiXmlElement* n_Parameter = n_AppNode->FirstChildElement("parameter"); n_Parameter != ITK_NULLPTR;
       n_Parameter = n_Parameter->NextSiblingElement() )
    {
    std::string key="-";
    key.append(GetChildNodeTextOf(n_Parameter, "key"));

    TiXmlElement* n_Values = ITK_NULLPTR;
    n_Values = n_Parameter->FirstChildElement("values");
    if(n_Values)
      {
      std::string values;
      for(TiXmlElement* n_Value = n_Values->FirstChildElement("value"); n_Value != ITK_NULLPTR;
          n_Value = n_Value->NextSiblingElement())
        {
        values.append(n_Value->GetText());
        values.append(" ");
        }
      values = values.substr(0,values.size()-1);
      expression.append(" ");
      expression.append(key);
      expression.append(" ");
      expression.append(values);
      }
    else
      {
      std::string value;
      value = GetChildNodeTextOf(n_Parameter, "value");

      expression.append(" ");
      expression.append(key);
      expression.append(" ");
      expression.append(value);

      std::string type = GetChildNodeTextOf(n_Parameter, "type");
      if (type == "OutputImage")
        {
        std::string t = GetChildNodeTextOf(n_Parameter, "pixtype");
        expression.append(" ");
        expression.append(t);
        }
      }
    }

  fclose(fp);

  return expression;
}

std::vector<std::string> PrepareVectorExpressionFromXML(std::string filename)
{
  std::vector<std::string> expression;

  if(filename.empty())
    {
    std::cerr <<"Input XML Filename is empty" << std::endl;
    return expression;
    }
  std::string ext = filename.substr(filename.size()-4,filename.size());
  if(ext != ".xml" )
    std::cerr << ext  << " is a wrong extension: Expected .xml " << __FILE__ << std::endl;

  // Open the xml file
  TiXmlDocument doc;

  //Use itksys::SystemTools::FOpen() and close it below because
  //TiXmlDocument::TiXmlFileOpen( ) is not exposed from tinyXML library. Even
  //though its available in the TiXmlDocument::SaveFile().
  FILE* fp =  itksys::SystemTools::Fopen(filename.c_str(), "rb");

  if (!doc.LoadFile(fp , TIXML_ENCODING_UTF8))
    {
    std::cerr << "Can't open file " << filename << std::endl;
    fclose(fp);
    exit(1);

    }

  TiXmlHandle handle(&doc);

  TiXmlElement *n_OTB;
  n_OTB = handle.FirstChild("OTB").Element();

  if(!n_OTB)
  {
    std::string info = "Input XML file " + filename + " is invalid.";
    std::cerr << info  << std::endl;
    fclose(fp);
    exit(1);
  }

  TiXmlElement *n_AppNode   = n_OTB->FirstChildElement("application");

  std::string moduleName;
  moduleName = GetChildNodeTextOf(n_AppNode, "name");

  expression.push_back(CleanWord(moduleName));

  for( TiXmlElement* n_Parameter = n_AppNode->FirstChildElement("parameter"); n_Parameter != ITK_NULLPTR;
       n_Parameter = n_Parameter->NextSiblingElement() )
    {
    std::string key="-";
    key.append(GetChildNodeTextOf(n_Parameter, "key"));
    expression.push_back(CleanWord(key));

    TiXmlElement* n_Values = ITK_NULLPTR;
    n_Values = n_Parameter->FirstChildElement("values");
    if(n_Values)
      {
      std::string values;
      for(TiXmlElement* n_Value = n_Values->FirstChildElement("value"); n_Value != ITK_NULLPTR;
          n_Value = n_Value->NextSiblingElement())
        {
        expression.push_back(CleanWord(n_Value->GetText()));
        }
      }
    else
      {
      std::string value;
      value = GetChildNodeTextOf(n_Parameter, "value");
      expression.push_back(CleanWord(value));

      std::string type = GetChildNodeTextOf(n_Parameter, "type");
      if (type == "OutputImage")
        {
        std::string t = GetChildNodeTextOf(n_Parameter, "pixtype");
        expression.push_back(CleanWord(t));
        }
      }
    }

  fclose(fp);

  return expression;
}

std::string CleanWord(const std::string & word)
{
  std::string res("");
  // Suppress whitespace characters at the beginning and ending of the string
  std::string::size_type cleanStart = word.find_first_not_of(" \t");
  std::string::size_type cleanEnd = word.find_last_not_of(" \t\f\v\n\r");
  // cleanStart == npos implies cleanEnd == npos
  if (cleanEnd != std::string::npos)
    {
    res = word.substr(cleanStart, cleanEnd - cleanStart + 1);
    }
  return res;
}

void ShowUsage(char* argv[])
{
  std::cerr << "Usage: " << argv[0] << " module_name [MODULEPATH] [arguments]" << std::endl;
}

int main(int argc, char* argv[])
{
  #ifdef OTB_USE_MPI
  otb::MPIConfig::Instance()->Init(argc,argv);
  #endif

  if (argc < 2)
  {
      ShowUsage(argv);
      return false;
  }

  std::vector<std::string> vexp;

  std::string exp;
  if (strcmp(argv[1], "-inxml") == 0)
    {
    vexp = PrepareVectorExpressionFromXML(argv[2]);
    }
  else
    {
    // Construct the string expression
    for (int i = 1; i < argc; i++)
      {
      std::string strarg(argv[i]);
      std::string cleanArg = CleanWord(strarg);
      if (cleanArg.empty())
        {
        // Empty argument !
        continue;
        }
      vexp.push_back(cleanArg);
      }
    }

  typedef otb::Wrapper::CommandLineLauncher LauncherType;
  LauncherType::Pointer launcher = LauncherType::New();

  if (vexp.empty())
  {
    ShowUsage(argv);
    return false;
  }

  bool success = launcher->Load(vexp) && launcher->ExecuteAndWriteOutput();

  // shutdown MPI after application finished
  #ifdef OTB_USE_MPI
  otb::MPIConfig::Instance()->terminate();
  #endif
  return success ? EXIT_SUCCESS : EXIT_FAILURE;
}

const std::string GetChildNodeTextOf(TiXmlElement *parentElement, std::string key)
{
  std::string value="";

  if(parentElement)
    {
    TiXmlElement* childElement = ITK_NULLPTR;
    childElement = parentElement->FirstChildElement(key.c_str());

    //same as childElement->GetText() does but that call is failing if there is
    //no such node.
    //but the below code works and is a replacement for GetText()
    if(childElement)
      {
      const TiXmlNode* child = childElement->FirstChild();
      if ( child )
        {
        const TiXmlText* childText = child->ToText();
        if ( childText )
          {
          value = childText->Value();
          }
        }
      }
    }
  return value;
}
<commit_msg>WRG: bool literal returned from main<commit_after>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperCommandLineLauncher.h"
#include "otb_tinyxml.h"
#include <vector>

#ifdef OTB_USE_MPI
#include "otbMPIConfig.h"
#endif

const std::string GetChildNodeTextOf(TiXmlElement *parentElement, std::string key);
std::string PrepareExpressionFromXML(std::string filename);
std::vector<std::string> PrepareVectorExpressionFromXML(std::string filename);
std::string CleanWord(const std::string & word);

std::string PrepareExpressionFromXML(std::string filename)
{
  std::string expression;

  if(filename.empty())
    {
    std::cerr <<"Input XML Filename is empty" << std::endl;
    return expression;
    }
  std::string ext = filename.substr(filename.size()-4,filename.size());
  if(ext != ".xml" )
    std::cerr << ext  << " is a wrong extension: Expected .xml " << __FILE__ << std::endl;

  // Open the xml file
  TiXmlDocument doc;

  //Use itksys::SystemTools::FOpen() and close it below because
  //TiXmlDocument::TiXmlFileOpen( ) is not exposed from tinyXML library. Even
  //though its available in the TiXmlDocument::SaveFile().
  FILE* fp =  itksys::SystemTools::Fopen(filename.c_str(), "rb");

  if (!doc.LoadFile(fp , TIXML_ENCODING_UTF8))
    {
    std::cerr << "Can't open file " << filename << std::endl;
    fclose(fp);
    exit(1);

    }

  TiXmlHandle handle(&doc);

  TiXmlElement *n_OTB;
  n_OTB = handle.FirstChild("OTB").Element();

  if(!n_OTB)
  {
    std::string info = "Input XML file " + filename + " is invalid.";
    std::cerr << info  << std::endl;
    fclose(fp);
    exit(1);
  }

  TiXmlElement *n_AppNode   = n_OTB->FirstChildElement("application");

  std::string moduleName;
  moduleName = GetChildNodeTextOf(n_AppNode, "name");
  /*
  AddMetaData("appname", app_Name);

  app_Descr = this_->GetChildNodeTextOf(n_AppNode, "descr");
  AddMetaData("appdescr", app_Descr);

  TiXmlElement* n_Doc    = n_AppNode->FirstChildElement("doc");

  std::string doc_Name, doc_Descr, doc_Author, doc_Limitation, doc_SeeAlso;

  doc_Name = this_->GetChildNodeTextOf(n_Doc, "name");
  AddMetaData("docname", doc_Name);

  doc_Descr = this_->GetChildNodeTextOf(n_Doc, "longdescr");
  AddMetaData("doclongdescr", doc_Descr);

  doc_Author = this_->GetChildNodeTextOf(n_Doc, "authors");
  AddMetaData("docauthors", doc_Author);

  doc_Limitation = this_->GetChildNodeTextOf(n_Doc, "limitations");
  AddMetaData("doclimitations", doc_Limitation);

  doc_SeeAlso = this_->GetChildNodeTextOf(n_Doc, "seealso");
  AddMetaData("docseealso", doc_SeeAlso);
  */

  expression.append(moduleName);

  for( TiXmlElement* n_Parameter = n_AppNode->FirstChildElement("parameter"); n_Parameter != ITK_NULLPTR;
       n_Parameter = n_Parameter->NextSiblingElement() )
    {
    std::string key="-";
    key.append(GetChildNodeTextOf(n_Parameter, "key"));

    TiXmlElement* n_Values = ITK_NULLPTR;
    n_Values = n_Parameter->FirstChildElement("values");
    if(n_Values)
      {
      std::string values;
      for(TiXmlElement* n_Value = n_Values->FirstChildElement("value"); n_Value != ITK_NULLPTR;
          n_Value = n_Value->NextSiblingElement())
        {
        values.append(n_Value->GetText());
        values.append(" ");
        }
      values = values.substr(0,values.size()-1);
      expression.append(" ");
      expression.append(key);
      expression.append(" ");
      expression.append(values);
      }
    else
      {
      std::string value;
      value = GetChildNodeTextOf(n_Parameter, "value");

      expression.append(" ");
      expression.append(key);
      expression.append(" ");
      expression.append(value);

      std::string type = GetChildNodeTextOf(n_Parameter, "type");
      if (type == "OutputImage")
        {
        std::string t = GetChildNodeTextOf(n_Parameter, "pixtype");
        expression.append(" ");
        expression.append(t);
        }
      }
    }

  fclose(fp);

  return expression;
}

std::vector<std::string> PrepareVectorExpressionFromXML(std::string filename)
{
  std::vector<std::string> expression;

  if(filename.empty())
    {
    std::cerr <<"Input XML Filename is empty" << std::endl;
    return expression;
    }
  std::string ext = filename.substr(filename.size()-4,filename.size());
  if(ext != ".xml" )
    std::cerr << ext  << " is a wrong extension: Expected .xml " << __FILE__ << std::endl;

  // Open the xml file
  TiXmlDocument doc;

  //Use itksys::SystemTools::FOpen() and close it below because
  //TiXmlDocument::TiXmlFileOpen( ) is not exposed from tinyXML library. Even
  //though its available in the TiXmlDocument::SaveFile().
  FILE* fp =  itksys::SystemTools::Fopen(filename.c_str(), "rb");

  if (!doc.LoadFile(fp , TIXML_ENCODING_UTF8))
    {
    std::cerr << "Can't open file " << filename << std::endl;
    fclose(fp);
    exit(1);

    }

  TiXmlHandle handle(&doc);

  TiXmlElement *n_OTB;
  n_OTB = handle.FirstChild("OTB").Element();

  if(!n_OTB)
  {
    std::string info = "Input XML file " + filename + " is invalid.";
    std::cerr << info  << std::endl;
    fclose(fp);
    exit(1);
  }

  TiXmlElement *n_AppNode   = n_OTB->FirstChildElement("application");

  std::string moduleName;
  moduleName = GetChildNodeTextOf(n_AppNode, "name");

  expression.push_back(CleanWord(moduleName));

  for( TiXmlElement* n_Parameter = n_AppNode->FirstChildElement("parameter"); n_Parameter != ITK_NULLPTR;
       n_Parameter = n_Parameter->NextSiblingElement() )
    {
    std::string key="-";
    key.append(GetChildNodeTextOf(n_Parameter, "key"));
    expression.push_back(CleanWord(key));

    TiXmlElement* n_Values = ITK_NULLPTR;
    n_Values = n_Parameter->FirstChildElement("values");
    if(n_Values)
      {
      std::string values;
      for(TiXmlElement* n_Value = n_Values->FirstChildElement("value"); n_Value != ITK_NULLPTR;
          n_Value = n_Value->NextSiblingElement())
        {
        expression.push_back(CleanWord(n_Value->GetText()));
        }
      }
    else
      {
      std::string value;
      value = GetChildNodeTextOf(n_Parameter, "value");
      expression.push_back(CleanWord(value));

      std::string type = GetChildNodeTextOf(n_Parameter, "type");
      if (type == "OutputImage")
        {
        std::string t = GetChildNodeTextOf(n_Parameter, "pixtype");
        expression.push_back(CleanWord(t));
        }
      }
    }

  fclose(fp);

  return expression;
}

std::string CleanWord(const std::string & word)
{
  std::string res("");
  // Suppress whitespace characters at the beginning and ending of the string
  std::string::size_type cleanStart = word.find_first_not_of(" \t");
  std::string::size_type cleanEnd = word.find_last_not_of(" \t\f\v\n\r");
  // cleanStart == npos implies cleanEnd == npos
  if (cleanEnd != std::string::npos)
    {
    res = word.substr(cleanStart, cleanEnd - cleanStart + 1);
    }
  return res;
}

void ShowUsage(char* argv[])
{
  std::cerr << "Usage: " << argv[0] << " module_name [MODULEPATH] [arguments]" << std::endl;
}

int main(int argc, char* argv[])
{
  #ifdef OTB_USE_MPI
  otb::MPIConfig::Instance()->Init(argc,argv);
  #endif

  if (argc < 2)
  {
      ShowUsage(argv);
      return EXIT_FAILURE;
  }

  std::vector<std::string> vexp;

  std::string exp;
  if (strcmp(argv[1], "-inxml") == 0)
    {
    vexp = PrepareVectorExpressionFromXML(argv[2]);
    }
  else
    {
    // Construct the string expression
    for (int i = 1; i < argc; i++)
      {
      std::string strarg(argv[i]);
      std::string cleanArg = CleanWord(strarg);
      if (cleanArg.empty())
        {
        // Empty argument !
        continue;
        }
      vexp.push_back(cleanArg);
      }
    }

  typedef otb::Wrapper::CommandLineLauncher LauncherType;
  LauncherType::Pointer launcher = LauncherType::New();

  if (vexp.empty())
  {
    ShowUsage(argv);
    return EXIT_FAILURE;
  }

  bool success = launcher->Load(vexp) && launcher->ExecuteAndWriteOutput();

  // shutdown MPI after application finished
  #ifdef OTB_USE_MPI
  otb::MPIConfig::Instance()->terminate();
  #endif
  return success ? EXIT_SUCCESS : EXIT_FAILURE;
}

const std::string GetChildNodeTextOf(TiXmlElement *parentElement, std::string key)
{
  std::string value="";

  if(parentElement)
    {
    TiXmlElement* childElement = ITK_NULLPTR;
    childElement = parentElement->FirstChildElement(key.c_str());

    //same as childElement->GetText() does but that call is failing if there is
    //no such node.
    //but the below code works and is a replacement for GetText()
    if(childElement)
      {
      const TiXmlNode* child = childElement->FirstChild();
      if ( child )
        {
        const TiXmlText* childText = child->ToText();
        if ( childText )
          {
          value = childText->Value();
          }
        }
      }
    }
  return value;
}
<|endoftext|>


<commit_before>#include <chrono>
#include <ostream>

#include <sdd/values/bitset.hh>

#include "mc/units/concurrent_units.hh"

namespace pnmc { namespace mc { namespace units {

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

namespace /* anonymous */{

struct nested_query_visitor
{
  using result_type = bool;

  const sdd::values::flat_set<unsigned int>& empty;
  const unsigned int j;

  nested_query_visitor(const sdd::values::flat_set<unsigned int>& empty, unsigned int j)
    : empty(empty), j(j)
  {}

  bool
  operator()(const sdd::zero_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|0|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::one_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|1|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::hierarchical_node<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "Hierarchy");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::flat_node<sdd_conf>& node, const order& o)
  const noexcept
  {
    if (o.identifier().user() == j)
    {
      for (const auto& arc : node)
      {
        if (arc.valuation() != empty)
        {
          return true;
        }
      }
    }
    else
    {
      for (const auto& arc : node)
      {
        if (visit(*this, arc.successor(), o.next()))
        {
          return true;
        }
      }
    }
    return false;
  }
};

struct query_visitor
{
  using result_type = bool;

  const sdd::values::flat_set<unsigned int>& empty;
  const unsigned int i;
  const unsigned int j;

  query_visitor(const sdd::values::flat_set<unsigned int>& empty, unsigned int i, unsigned int j)
    : empty(empty), i(i), j(j)
  {}

  bool
  operator()(const sdd::zero_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|0|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::one_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|1|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::hierarchical_node<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "Hierarchy");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::flat_node<sdd_conf>& node, const order& o)
  const noexcept
  {
    if (o.identifier().user() == i)
    {
      for (const auto& arc : node)
      {
        if (arc.valuation() != empty)
        {
          if (visit(nested_query_visitor(empty, j), arc.successor(), o.next()))
          {
            return true;
          }
        }
      }
    }
    else
    {
      for (const auto& arc : node)
      {
        if (visit(*this, arc.successor(), o.next()))
        {
          return true;
        }
      }
    }
    return false;
  }
};

bool
query(SDD states, const order& o, unsigned int i, unsigned int j)
{
  const sdd::values::flat_set<unsigned int> empty_unit = {0};
  if (o.node(i) < o.node(j)) // does 'i' is before 'j' in the order?
  {
    return visit(query_visitor(empty_unit, i, j), states, o);
  }
  else
  {
    return visit(query_visitor(empty_unit, j, i), states, o);
  }
}

} // namespace anonymous

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

void
compute_concurrent_units( const conf::pnmc_configuration& conf, const pn::net& net
                        , const sdd::order<sdd_conf>& o, SDD states)
{
  namespace chrono = std::chrono;
  chrono::time_point<chrono::system_clock> start = chrono::system_clock::now();

  const auto nb_units = net.units_size();
  unsigned int j_end = 1;
  for (unsigned int i = 0; i < nb_units; ++i, ++j_end)
  {
    for (unsigned int j = 0; j < j_end; ++j)
    {
      if (i == j)
      {
        std::cout << "0 ";
      }
      else
      {
        std::cout << (query(states, o, i, j) ? "1 " : "0 ");
      }
    }
    std::cout << "\n";
  }

  chrono::time_point<chrono::system_clock> end = chrono::system_clock::now();
  const std::size_t elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();
  if (conf.show_time)
  {
    std::cout << "Concurrent units computation time: " << elapsed << "s\n";
  }
}

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

}}} // namespace pnmc::mc::units
<commit_msg>Use a cache of visited nodes when computing concurrent units.<commit_after>#include <chrono>
#include <ostream>
#include <unordered_set>

#include <sdd/values/bitset.hh>

#include "mc/units/concurrent_units.hh"

namespace pnmc { namespace mc { namespace units {

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

namespace /* anonymous */{

struct nested_query_visitor
{
  using result_type = bool;

  const sdd::values::flat_set<unsigned int>& empty;
  const unsigned int j;
  mutable std::unordered_set<const sdd::flat_node<sdd_conf>*> cache;

  nested_query_visitor(const sdd::values::flat_set<unsigned int>& empty, unsigned int j)
    : empty(empty), j(j), cache()
  {}

  bool
  operator()(const sdd::zero_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|0|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::one_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|1|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::hierarchical_node<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "Hierarchy");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::flat_node<sdd_conf>& node, const order& o)
  const noexcept
  {
    const auto insertion = cache.emplace(&node);
    if (insertion.second)
    {
      if (o.identifier().user() == j)
      {
        for (const auto& arc : node)
        {
          if (arc.valuation() != empty)
          {
            return true;
          }
        }
      }
      else
      {
        for (const auto& arc : node)
        {
          if (visit(*this, arc.successor(), o.next()))
          {
            return true;
          }
        }
      }
    }
    return false;
  }
};

struct query_visitor
{
  using result_type = bool;

  const sdd::values::flat_set<unsigned int>& empty;
  const unsigned int i;
  const unsigned int j;
  mutable std::unordered_set<const sdd::flat_node<sdd_conf>*> cache;

  query_visitor(const sdd::values::flat_set<unsigned int>& empty, unsigned int i, unsigned int j)
    : empty(empty), i(i), j(j), cache()
  {}

  bool
  operator()(const sdd::zero_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|0|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::one_terminal<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "|1|");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::hierarchical_node<sdd_conf>&, const order&)
  const noexcept
  {
    assert(false && "Hierarchy");
    __builtin_unreachable();
  }

  bool
  operator()(const sdd::flat_node<sdd_conf>& node, const order& o)
  const noexcept
  {
    const auto insertion = cache.emplace(&node);
    if (insertion.second)
    {
      if (o.identifier().user() == i)
      {
        for (const auto& arc : node)
        {
          if (arc.valuation() != empty)
          {
            if (visit(nested_query_visitor(empty, j), arc.successor(), o.next()))
            {
              return true;
            }
          }
        }
      }
      else
      {
        for (const auto& arc : node)
        {
          if (visit(*this, arc.successor(), o.next()))
          {
            return true;
          }
        }
      }
    }
    return false;
  }
};

bool
query(SDD states, const order& o, unsigned int i, unsigned int j)
{
  const sdd::values::flat_set<unsigned int> empty_unit = {0};
  if (o.node(i) < o.node(j)) // does 'i' is before 'j' in the order?
  {
    return visit(query_visitor(empty_unit, i, j), states, o);
  }
  else
  {
    return visit(query_visitor(empty_unit, j, i), states, o);
  }
}

} // namespace anonymous

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

void
compute_concurrent_units( const conf::pnmc_configuration& conf, const pn::net& net
                        , const sdd::order<sdd_conf>& o, SDD states)
{
  namespace chrono = std::chrono;
  chrono::time_point<chrono::system_clock> start = chrono::system_clock::now();

  const auto nb_units = net.units_size();
  unsigned int j_end = 1;
  for (unsigned int i = 0; i < nb_units; ++i, ++j_end)
  {
    for (unsigned int j = 0; j < j_end; ++j)
    {
      if (i == j)
      {
        std::cout << "0 ";
      }
      else
      {
        std::cout << (query(states, o, i, j) ? "1 " : "0 ");
      }
    }
    std::cout << "\n";
  }

  chrono::time_point<chrono::system_clock> end = chrono::system_clock::now();
  const std::size_t elapsed = chrono::duration_cast<chrono::seconds>(end-start).count();
  if (conf.show_time)
  {
    std::cout << "Concurrent units computation time: " << elapsed << "s\n";
  }
}

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

}}} // namespace pnmc::mc::units
<|endoftext|>


<commit_before>#ifndef __AIRSCHED_BOM_SEGMENTPATHPERIODKEY_HPP
#define __AIRSCHED_BOM_SEGMENTPATHPERIODKEY_HPP

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <iosfwd>
#include <string>
// StdAir
#include <stdair/stdair_basic_types.hpp>
#include <stdair/stdair_date_time_types.hpp>
#include <stdair/bom/KeyAbstract.hpp>
#include <stdair/bom/PeriodStruct.hpp>
// AirSched
#include <airsched/bom/SegmentPathPeriodTypes.hpp>

/// Forward declarations
namespace boost {
  namespace serialization {
    class access;
  }
}

namespace AIRSCHED {

  /**
   * @brief Structure representing the key of a segment/path.
   *
   * That key specifies a travel solution from a geographical point
   * (origin airport) to another (destination airport).
   */
  struct SegmentPathPeriodKey : public stdair::KeyAbstract {
    friend class boost::serialization::access;

    // /////////// Constructors and destructors ///////////
  public:
    /**
     * Constructor.
     */
    SegmentPathPeriodKey (const stdair::PeriodStruct&,
                          const stdair::Duration_T& iBoardingTime,
                          const stdair::Duration_T& iElapsed,
                          const DateOffsetList_T&,
                          const stdair::NbOfAirlines_T&);

    /**
     * Default constructor.
     */
    SegmentPathPeriodKey();

    /**
     * Copy constructor.
     */
    SegmentPathPeriodKey (const SegmentPathPeriodKey&);

    /**
     * Destructor.
     */
    ~SegmentPathPeriodKey();

  public:
    // /////////// Getters //////////
    /**
     * Get the active days-of-week.
     */
    const stdair::PeriodStruct& getPeriod() const {
      return _period;
    }

    /**
     * Get the list of boarding date off-sets.
     */
    const DateOffsetList_T& getBoardingDateOffsetList() const {
      return _boardingDateOffsetList;
    }

    /**
     * Get the number of segments.
     */
    const stdair::NbOfSegments_T& getNbOfSegments() const {
      return _boardingDateOffsetList.size();
    }

    /**
     * Get the number of airlines.
     */
    const stdair::NbOfAirlines_T& getNbOfAirlines() const {
      return _nbOfAirlines;
    }

    /**
     * Get the elapsed time.
     */
    const stdair::Duration_T& getElapsedTime() const {
      return _elapsed;
    }

    /**
     * Get the boarding time.
     */
    const stdair::Duration_T& getBoardingTime() const {
      return _boardingTime;
    }

  public:
    // /////////// Setters //////////
    /** Set the active days-of-week. */
    void setPeriod (const stdair::PeriodStruct& iPeriod) {
      _period = iPeriod;
    }

    void setBoardingDateOffsetList (const DateOffsetList_T& iList) {
      _boardingDateOffsetList = iList;
    }

    /** Set the number of airlines. */
    void setNbOfAirlines (const stdair::NbOfAirlines_T& iNbOfAirlines) {
      _nbOfAirlines = iNbOfAirlines;
    }

    /** Set the elapsed time. */
    void setElapsedTime (const stdair::Duration_T& iElapsed) {
      _elapsed = iElapsed;
    }

    /** Set the boarding time. */
    void setBoardingTime (const stdair::Duration_T& iBoardingTime) {
      _boardingTime = iBoardingTime;
    }

  public:
    // /////////// Business methods ////////////
    /** Check if the key is valid (i.e. the departure period is valid). */
    const bool isValid () const {
      return _period.isValid ();
    }

  public:
    // /////////// Display support methods /////////
    /**
     * Dump a Business Object Key into an output stream.
     *
     * @param ostream& the output stream.
     */
    void toStream (std::ostream& ioOut) const;

    /**
     * Read a Business Object Key from an input stream.
     *
     * @param istream& the input stream.
     */
    void fromStream (std::istream& ioIn);

    /**
     * Get the serialised version of the Business Object Key.
     *
     * That string is unique, at the level of a given Business Object,
     * when among children of a given parent Business Object.
     *
     * For instance, "H" and "K" allow to differentiate among two
     * marketing classes for the same segment-date.
     */
    const std::string toString() const;

  public:
    // /////////// (Boost) Serialisation support methods /////////
    /**
     * Serialisation.
     */
    template<class Archive>
    void serialize (Archive& ar, const unsigned int iFileVersion);

  private:
    /**
     * Serialisation helper (allows to be sure the template method is
     * instantiated).
     */
    void serialisationImplementation();

  private:
    // ///////////////// Attributes ///////////////
    /**
     * Departure period.
     */
    stdair::PeriodStruct _period;

    /**
     * The boarding time.
     */
    stdair::Duration_T _boardingTime;

    /**
     * The elapsed time of the path.
     */
    stdair::Duration_T _elapsed;

    /**
     * The list of boarding date offsets of the segments compare to
     * the first one.
     */
    DateOffsetList_T _boardingDateOffsetList;

    /**
     * Number of airlines included in the path.
     */
    stdair::NbOfAirlines_T _nbOfAirlines;
  };

}
#endif // __AIRSCHED_BOM_SEGMENTPATHPERIODKEY_HPP
<commit_msg>[Dev] Fixed a potential bug (returning a reference on a temporary).<commit_after>#ifndef __AIRSCHED_BOM_SEGMENTPATHPERIODKEY_HPP
#define __AIRSCHED_BOM_SEGMENTPATHPERIODKEY_HPP

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <iosfwd>
#include <string>
// StdAir
#include <stdair/stdair_basic_types.hpp>
#include <stdair/stdair_date_time_types.hpp>
#include <stdair/bom/KeyAbstract.hpp>
#include <stdair/bom/PeriodStruct.hpp>
// AirSched
#include <airsched/bom/SegmentPathPeriodTypes.hpp>

/// Forward declarations
namespace boost {
  namespace serialization {
    class access;
  }
}

namespace AIRSCHED {

  /**
   * @brief Structure representing the key of a segment/path.
   *
   * That key specifies a travel solution from a geographical point
   * (origin airport) to another (destination airport).
   */
  struct SegmentPathPeriodKey : public stdair::KeyAbstract {
    friend class boost::serialization::access;

    // /////////// Constructors and destructors ///////////
  public:
    /**
     * Constructor.
     */
    SegmentPathPeriodKey (const stdair::PeriodStruct&,
                          const stdair::Duration_T& iBoardingTime,
                          const stdair::Duration_T& iElapsed,
                          const DateOffsetList_T&,
                          const stdair::NbOfAirlines_T&);

    /**
     * Default constructor.
     */
    SegmentPathPeriodKey();

    /**
     * Copy constructor.
     */
    SegmentPathPeriodKey (const SegmentPathPeriodKey&);

    /**
     * Destructor.
     */
    ~SegmentPathPeriodKey();

  public:
    // /////////// Getters //////////
    /**
     * Get the active days-of-week.
     */
    const stdair::PeriodStruct& getPeriod() const {
      return _period;
    }

    /**
     * Get the list of boarding date off-sets.
     */
    const DateOffsetList_T& getBoardingDateOffsetList() const {
      return _boardingDateOffsetList;
    }

    /**
     * Get the number of segments.
     */
    const stdair::NbOfSegments_T getNbOfSegments() const {
      return _boardingDateOffsetList.size();
    }

    /**
     * Get the number of airlines.
     */
    const stdair::NbOfAirlines_T& getNbOfAirlines() const {
      return _nbOfAirlines;
    }

    /**
     * Get the elapsed time.
     */
    const stdair::Duration_T& getElapsedTime() const {
      return _elapsed;
    }

    /**
     * Get the boarding time.
     */
    const stdair::Duration_T& getBoardingTime() const {
      return _boardingTime;
    }

  public:
    // /////////// Setters //////////
    /** Set the active days-of-week. */
    void setPeriod (const stdair::PeriodStruct& iPeriod) {
      _period = iPeriod;
    }

    void setBoardingDateOffsetList (const DateOffsetList_T& iList) {
      _boardingDateOffsetList = iList;
    }

    /** Set the number of airlines. */
    void setNbOfAirlines (const stdair::NbOfAirlines_T& iNbOfAirlines) {
      _nbOfAirlines = iNbOfAirlines;
    }

    /** Set the elapsed time. */
    void setElapsedTime (const stdair::Duration_T& iElapsed) {
      _elapsed = iElapsed;
    }

    /** Set the boarding time. */
    void setBoardingTime (const stdair::Duration_T& iBoardingTime) {
      _boardingTime = iBoardingTime;
    }

  public:
    // /////////// Business methods ////////////
    /** Check if the key is valid (i.e. the departure period is valid). */
    const bool isValid () const {
      return _period.isValid ();
    }

  public:
    // /////////// Display support methods /////////
    /**
     * Dump a Business Object Key into an output stream.
     *
     * @param ostream& the output stream.
     */
    void toStream (std::ostream& ioOut) const;

    /**
     * Read a Business Object Key from an input stream.
     *
     * @param istream& the input stream.
     */
    void fromStream (std::istream& ioIn);

    /**
     * Get the serialised version of the Business Object Key.
     *
     * That string is unique, at the level of a given Business Object,
     * when among children of a given parent Business Object.
     *
     * For instance, "H" and "K" allow to differentiate among two
     * marketing classes for the same segment-date.
     */
    const std::string toString() const;

  public:
    // /////////// (Boost) Serialisation support methods /////////
    /**
     * Serialisation.
     */
    template<class Archive>
    void serialize (Archive& ar, const unsigned int iFileVersion);

  private:
    /**
     * Serialisation helper (allows to be sure the template method is
     * instantiated).
     */
    void serialisationImplementation();

  private:
    // ///////////////// Attributes ///////////////
    /**
     * Departure period.
     */
    stdair::PeriodStruct _period;

    /**
     * The boarding time.
     */
    stdair::Duration_T _boardingTime;

    /**
     * The elapsed time of the path.
     */
    stdair::Duration_T _elapsed;

    /**
     * The list of boarding date offsets of the segments compare to
     * the first one.
     */
    DateOffsetList_T _boardingDateOffsetList;

    /**
     * Number of airlines included in the path.
     */
    stdair::NbOfAirlines_T _nbOfAirlines;
  };

}
#endif // __AIRSCHED_BOM_SEGMENTPATHPERIODKEY_HPP
<|endoftext|>


<commit_before>#include "keilo_server.hpp"

#include <utility>
#include <thread>
#include <iostream>
#include <sstream>
#include <string>
#include <exception>

#include <boost/asio.hpp>

namespace asio = boost::asio;
namespace ip = asio::ip;

keilo_server::keilo_server(int port) :
	m_application(new keilo_application()),
	m_clients(std::list < ip::tcp::socket > ()),
	m_client_processes(std::list<std::thread>()),
	m_port(port),
	m_acceptor(m_io_service, ip::tcp::endpoint(ip::address::from_string("127.0.0.1"), m_port)),
	print_thread(std::thread(&keilo_server::print_output, this)),
	accept_thread(std::thread(&keilo_server::accept_client, this))
{
}

keilo_server::~keilo_server()
{
	if (running.load())
		running = false;
	if (accept_thread.joinable())
		accept_thread.join();
	if (print_thread.joinable())
		print_thread.join();
	for (auto& client : m_clients)
		client.close();
	m_acceptor.close();
}

void keilo_server::run()
{
	m_acceptor.listen(5);
	run_local();
}

void keilo_server::run_local()
{
	running = true;
	std::string input;
	while (running.load()) {
		while (printing.load());
		std::stringstream select_status;
		if (selected_database) {
			select_status << "[" << selected_database->get_name();
			if (selected_table)
				select_status << "_" << selected_table->get_name();
			select_status << "]> ";
		}
		else
			select_status << "[none]> ";

		std::cout << select_status.str();

		if (std::getline(std::cin, input); input == "exit") {
			running = false;
			break;
		}

		push_output(process_message(input));
	}
}

std::string keilo_server::import_file(std::string file_name, bool ps)
{
	selected_database = nullptr;
	selected_table = nullptr;
	auto output = m_application->import_file(file_name);
	if (ps) {
		push_output(output);
	}
	return output;
}

void keilo_server::print_output()
{
	while (!running.load());
	while (running.load()) {
		m_output_mutex.lock();
		while (m_outputs.size() > 0) {
			printing = true;
			std::cout << m_outputs.front() << std::endl;
			m_outputs.pop();
		}
		m_output_mutex.unlock();
		if (printing.load())
			printing = false;
	}
}

void keilo_server::push_output(const std::string message)
{
	m_output_mutex.lock();
	m_outputs.push(message);
	m_output_mutex.unlock();
}

void keilo_server::accept_client()
{
	while (running.load()) {
		ip::tcp::socket _client(m_io_service);
		m_acceptor.accept(_client);

		m_clients.push_back(std::move(_client));

		m_client_processes.push_back(std::thread([&]() {
			auto found = false;
			do {
				process_client(_client);
				for (const auto& client : m_clients) {
					if (client.remote_endpoint().address().to_string() == _client.remote_endpoint().address().to_string() &&
						client.remote_endpoint().port() == _client.remote_endpoint().port())
					{
						found = true;
						break;
					}
				}
			} while (found);
		}));
	}
}

void keilo_server::process_client(ip::tcp::socket& client)
{
	asio::streambuf read_buffer;
	asio::read(client, read_buffer);

	std::string read_data = asio::buffer_cast<const char*>(read_buffer.data());
	read_data.erase(--read_data.end());

	asio::write(client, asio::buffer(process_message(read_data.c_str())));
}

const std::string keilo_server::process_message(std::string message)
{

	std::stringstream result;

	if (message.find(CREATE) != std::string::npos) {
		if (auto pos = message.find(DATABASE); pos != std::string::npos)
			result << create_database(message, pos + DATABASE.length());
		else if (auto pos = message.find(TABLE); pos != std::string::npos)
			result << create_table(message, pos + TABLE.length());
		else
			result << "Unknown command.";
	}
	else if (message.find(SELECT) != std::string::npos) {
		if (auto pos = message.find(DATABASE); pos != std::string::npos)
			result << select_database(message, pos + DATABASE.length());
		else if (auto pos = message.find(TABLE); pos != std::string::npos)
			result << select_table(message, pos + TABLE.length());
		else if (auto pos = message.find(RECORD); pos != std::string::npos)
			result << select_record(message, pos + RECORD.length());
		else
			result << "Unknown command.";
	}
	else if (auto pos = message.find(JOIN); pos != std::string::npos) {
		result << join_table(message, pos + JOIN.length());
	}
	else if (auto pos = message.find(INSERT); pos != std::string::npos) {
		result << insert_record(message, pos + INSERT.length());
	}
	else if (auto pos = message.find(UPDATE); pos != std::string::npos) {
		result << update_record(message, pos + UPDATE.length());
	}
	else if (auto pos = message.find(REMOVE); pos != std::string::npos) {
		result << remove_record(message, pos + REMOVE.length());
	}
	else if (auto pos = message.find(DROP); pos != std::string::npos) {
		result << drop_table(message, pos + DROP.length());
	}
	else if (auto pos = message.find(IMPORT_FILE); pos != std::string::npos) {
		result << import_database(message, pos + IMPORT_FILE.length());
	}
	else if (auto pos = message.find(EXPORT_FILE); pos != std::string::npos) {
		result << export_database(message, pos + EXPORT_FILE.length());
	}
	else if (auto pos = message.find(CLEAR); pos != std::string::npos) {
		system("cls");
	}
	else
		result << "Unknown command.";

	return result.str();
}

void keilo_server::disconnect_client(ip::tcp::socket _client)
{
	auto selected_client = m_clients.end();

	for (auto it = m_clients.begin(); it != m_clients.end(); ++it) {
		if (it->remote_endpoint().address().to_string() == _client.remote_endpoint().address().to_string() &&
			it->remote_endpoint().port() == _client.remote_endpoint().port())
		{
			selected_client = it;
			break;
		}
	}

	if (selected_client == m_clients.end())
		throw std::exception("[disconnect_client] Could not find client.");

	push_output(("[disconnect_client] (" + selected_client->remote_endpoint().address().to_string() + ") disconnected.").c_str());
	selected_client->close();
	m_clients.erase(selected_client);

	for (auto& process : m_client_processes) {
		if (process.joinable())
			process.join();
	}
}

std::string keilo_server::create_database(std::string message, size_t pos)
{
	if (pos >= message.length())
		return "Syntax error";
	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	return m_application->create_database(name.str());
}

std::string keilo_server::select_database(std::string message, size_t pos)
{
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	if (selected_database = m_application->select_database(name.str()); selected_database)
		return "Successfully selected database that was named \"" + name.str() + "\".";
	else
		return "Database that was named \"" + name.str() + "\" does not exist in server";
}

std::string keilo_server::export_database(std::string message, size_t pos)
{
	if (!selected_database)
		return "Please select database";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream file_name;
	while (message[pos] != ';' && pos < message.length())
		file_name << message[pos++];
	file_name << ".klo";

	return  m_application->export_database(selected_database->get_name(), file_name.str());
}

std::string keilo_server::import_database(std::string message, size_t pos)
{
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream file_name;
	while (message[pos] != ';' && pos < message.length())
		file_name << message[pos++];
	return import_file(file_name.str(), false);
}

std::string keilo_server::create_table(std::string message, size_t pos)
{
	if (!selected_database)
		return "Please select database";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	return selected_database->create_table(name.str());
}

std::string keilo_server::select_table(std::string message, size_t pos)
{
	if (!selected_database)
		return "Please select database";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	if (selected_table = selected_database->select_table(name.str()); selected_table)
		return "Successfully selected table that was named \"" + name.str() + "\".";
	else
		return "Table that was named \"" + name.str() + "\" does not exist in database \"" + selected_database->get_name() + "\".";
}

std::string keilo_server::drop_table(std::string message, size_t pos)
{
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	return selected_database->drop_table(name.str());
}

std::string keilo_server::select_record(std::string message, size_t pos)
{
	if (!selected_table)
		return "Please select table.";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream identifier;
	while (message[pos] != ':' && pos < message.length())
		identifier << message[pos++];
	pos += 1;
	std::stringstream value;
	while (message[pos] != ';' && pos < message.length())
		value << message[pos++];

	auto record = selected_table->select_record(keilo_instance{ identifier.str(), value.str() });
	std::stringstream selected_record;

	if (record.size() > 0) {
		selected_record << "(" << std::endl;
		for (const auto& instance : record)
			selected_record << instance.first << ":" << instance.second << ";" << std::endl;
		selected_record << ")" << std::endl;
	}
	else
		selected_record << "There is no record that has " << value.str() << " as " << identifier.str() << "in table " << selected_table->get_name() << "." << std::endl;

	return selected_record.str();
}

std::string keilo_server::insert_record(std::string message, size_t pos)
{
	//  ʿ
	/*
	while (message[pos - 1] != '(')
		pos++;

	keilo_record record;
	while (message[pos] != ')') {
		while (message[pos] != ';') {
			std::stringstream identifier;
			while (message[pos] != ':')
				identifier << message[pos++];

			std::stringstream value;
			while (message[pos] != ';')
				value << message[pos++];
			record.push_back(keilo_instance{ identifier.str(), value.str() });
		}
	}*/

	if (!selected_table)
		return "Please select table";

	keilo_record record;

	while (pos < message.length()) {
		std::stringstream identifier;
		while (message[pos] != ':' && pos < message.length())
			identifier << message[pos++];
		pos += 1;

		std::stringstream value;
		while ((message[pos] != ',' && message[pos] != ';') && pos < message.length())
			value << message[pos++];

		record.push_back(keilo_instance{ identifier.str(), value.str() });

		while (message[pos - 1] != ' ' && message[pos - 1] != ','  && message[pos - 1] != ';' && pos < message.length())
			pos++;
	}

	return selected_table->insert(record);
}

std::string keilo_server::update_record(std::string message, size_t pos)
{
	if (!selected_table)
		return "Please select table";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream condition_identifier;
	while (message[pos] != ':' && pos < message.length())
		condition_identifier << message[pos++];
	pos += 1;

	std::stringstream condition_value;
	while (message[pos] != ' '&& pos < message.length())
		condition_value << message[pos++];
	pos += 1;

	std::stringstream new_identifier;
	while (message[pos] != ':'&& pos < message.length())
		new_identifier << message[pos++];
	pos += 1;

	std::stringstream new_value;
	while (message[pos] != ';'&& pos < message.length())
		new_value << message[pos++];
	pos += 1;

	return selected_table->update(keilo_instance{ condition_identifier.str(), condition_value.str() }, keilo_instance{ new_identifier.str(), new_value.str() });
}

std::string keilo_server::remove_record(std::string message, size_t pos)
{
	if (!selected_table)
		return "Please select table";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream identifier;
	while (message[pos] != ':' && pos < message.length())
		identifier << message[pos++];
	pos += 1;
	std::stringstream value;
	while (message[pos] != ';' && pos < message.length())
		value << message[pos++];

	return selected_table->remove(keilo_instance{ identifier.str(), value.str() });
}
<commit_msg>for system()<commit_after>#include "keilo_server.hpp"

#include <utility>
#include <thread>
#include <iostream>
#include <sstream>
#include <string>
#include <exception>
#include <cstdlib>

#include <boost/asio.hpp>

namespace asio = boost::asio;
namespace ip = asio::ip;

keilo_server::keilo_server(int port) :
	m_application(new keilo_application()),
	m_clients(std::list < ip::tcp::socket > ()),
	m_client_processes(std::list<std::thread>()),
	m_port(port),
	m_acceptor(m_io_service, ip::tcp::endpoint(ip::address::from_string("127.0.0.1"), m_port)),
	print_thread(std::thread(&keilo_server::print_output, this)),
	accept_thread(std::thread(&keilo_server::accept_client, this))
{
}

keilo_server::~keilo_server()
{
	if (running.load())
		running = false;
	if (accept_thread.joinable())
		accept_thread.join();
	if (print_thread.joinable())
		print_thread.join();
	for (auto& client : m_clients)
		client.close();
	m_acceptor.close();
}

void keilo_server::run()
{
	m_acceptor.listen(5);
	run_local();
}

void keilo_server::run_local()
{
	running = true;
	std::string input;
	while (running.load()) {
		while (printing.load());
		std::stringstream select_status;
		if (selected_database) {
			select_status << "[" << selected_database->get_name();
			if (selected_table)
				select_status << "_" << selected_table->get_name();
			select_status << "]> ";
		}
		else
			select_status << "[none]> ";

		std::cout << select_status.str();

		if (std::getline(std::cin, input); input == "exit") {
			running = false;
			break;
		}

		push_output(process_message(input));
	}
}

std::string keilo_server::import_file(std::string file_name, bool ps)
{
	selected_database = nullptr;
	selected_table = nullptr;
	auto output = m_application->import_file(file_name);
	if (ps) {
		push_output(output);
	}
	return output;
}

void keilo_server::print_output()
{
	while (!running.load());
	while (running.load()) {
		m_output_mutex.lock();
		while (m_outputs.size() > 0) {
			printing = true;
			std::cout << m_outputs.front() << std::endl;
			m_outputs.pop();
		}
		m_output_mutex.unlock();
		if (printing.load())
			printing = false;
	}
}

void keilo_server::push_output(const std::string message)
{
	m_output_mutex.lock();
	m_outputs.push(message);
	m_output_mutex.unlock();
}

void keilo_server::accept_client()
{
	while (running.load()) {
		ip::tcp::socket _client(m_io_service);
		m_acceptor.accept(_client);

		m_clients.push_back(std::move(_client));

		m_client_processes.push_back(std::thread([&]() {
			auto found = false;
			do {
				process_client(_client);
				for (const auto& client : m_clients) {
					if (client.remote_endpoint().address().to_string() == _client.remote_endpoint().address().to_string() &&
						client.remote_endpoint().port() == _client.remote_endpoint().port())
					{
						found = true;
						break;
					}
				}
			} while (found);
		}));
	}
}

void keilo_server::process_client(ip::tcp::socket& client)
{
	asio::streambuf read_buffer;
	asio::read(client, read_buffer);

	std::string read_data = asio::buffer_cast<const char*>(read_buffer.data());
	read_data.erase(--read_data.end());

	asio::write(client, asio::buffer(process_message(read_data.c_str())));
}

const std::string keilo_server::process_message(std::string message)
{

	std::stringstream result;

	if (message.find(CREATE) != std::string::npos) {
		if (auto pos = message.find(DATABASE); pos != std::string::npos)
			result << create_database(message, pos + DATABASE.length());
		else if (auto pos = message.find(TABLE); pos != std::string::npos)
			result << create_table(message, pos + TABLE.length());
		else
			result << "Unknown command.";
	}
	else if (message.find(SELECT) != std::string::npos) {
		if (auto pos = message.find(DATABASE); pos != std::string::npos)
			result << select_database(message, pos + DATABASE.length());
		else if (auto pos = message.find(TABLE); pos != std::string::npos)
			result << select_table(message, pos + TABLE.length());
		else if (auto pos = message.find(RECORD); pos != std::string::npos)
			result << select_record(message, pos + RECORD.length());
		else
			result << "Unknown command.";
	}
	else if (auto pos = message.find(JOIN); pos != std::string::npos) {
		result << join_table(message, pos + JOIN.length());
	}
	else if (auto pos = message.find(INSERT); pos != std::string::npos) {
		result << insert_record(message, pos + INSERT.length());
	}
	else if (auto pos = message.find(UPDATE); pos != std::string::npos) {
		result << update_record(message, pos + UPDATE.length());
	}
	else if (auto pos = message.find(REMOVE); pos != std::string::npos) {
		result << remove_record(message, pos + REMOVE.length());
	}
	else if (auto pos = message.find(DROP); pos != std::string::npos) {
		result << drop_table(message, pos + DROP.length());
	}
	else if (auto pos = message.find(IMPORT_FILE); pos != std::string::npos) {
		result << import_database(message, pos + IMPORT_FILE.length());
	}
	else if (auto pos = message.find(EXPORT_FILE); pos != std::string::npos) {
		result << export_database(message, pos + EXPORT_FILE.length());
	}
	else if (auto pos = message.find(CLEAR); pos != std::string::npos) {
		system("cls");
	}
	else
		result << "Unknown command.";

	return result.str();
}

void keilo_server::disconnect_client(ip::tcp::socket _client)
{
	auto selected_client = m_clients.end();

	for (auto it = m_clients.begin(); it != m_clients.end(); ++it) {
		if (it->remote_endpoint().address().to_string() == _client.remote_endpoint().address().to_string() &&
			it->remote_endpoint().port() == _client.remote_endpoint().port())
		{
			selected_client = it;
			break;
		}
	}

	if (selected_client == m_clients.end())
		throw std::exception("[disconnect_client] Could not find client.");

	push_output(("[disconnect_client] (" + selected_client->remote_endpoint().address().to_string() + ") disconnected.").c_str());
	selected_client->close();
	m_clients.erase(selected_client);

	for (auto& process : m_client_processes) {
		if (process.joinable())
			process.join();
	}
}

std::string keilo_server::create_database(std::string message, size_t pos)
{
	if (pos >= message.length())
		return "Syntax error";
	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	return m_application->create_database(name.str());
}

std::string keilo_server::select_database(std::string message, size_t pos)
{
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	if (selected_database = m_application->select_database(name.str()); selected_database)
		return "Successfully selected database that was named \"" + name.str() + "\".";
	else
		return "Database that was named \"" + name.str() + "\" does not exist in server";
}

std::string keilo_server::export_database(std::string message, size_t pos)
{
	if (!selected_database)
		return "Please select database";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream file_name;
	while (message[pos] != ';' && pos < message.length())
		file_name << message[pos++];
	file_name << ".klo";

	return  m_application->export_database(selected_database->get_name(), file_name.str());
}

std::string keilo_server::import_database(std::string message, size_t pos)
{
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream file_name;
	while (message[pos] != ';' && pos < message.length())
		file_name << message[pos++];
	return import_file(file_name.str(), false);
}

std::string keilo_server::create_table(std::string message, size_t pos)
{
	if (!selected_database)
		return "Please select database";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	return selected_database->create_table(name.str());
}

std::string keilo_server::select_table(std::string message, size_t pos)
{
	if (!selected_database)
		return "Please select database";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	if (selected_table = selected_database->select_table(name.str()); selected_table)
		return "Successfully selected table that was named \"" + name.str() + "\".";
	else
		return "Table that was named \"" + name.str() + "\" does not exist in database \"" + selected_database->get_name() + "\".";
}

std::string keilo_server::drop_table(std::string message, size_t pos)
{
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream name;
	while (message[pos] != ';' && pos < message.length())
		name << message[pos++];

	return selected_database->drop_table(name.str());
}

std::string keilo_server::select_record(std::string message, size_t pos)
{
	if (!selected_table)
		return "Please select table.";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream identifier;
	while (message[pos] != ':' && pos < message.length())
		identifier << message[pos++];
	pos += 1;
	std::stringstream value;
	while (message[pos] != ';' && pos < message.length())
		value << message[pos++];

	auto record = selected_table->select_record(keilo_instance{ identifier.str(), value.str() });
	std::stringstream selected_record;

	if (record.size() > 0) {
		selected_record << "(" << std::endl;
		for (const auto& instance : record)
			selected_record << instance.first << ":" << instance.second << ";" << std::endl;
		selected_record << ")" << std::endl;
	}
	else
		selected_record << "There is no record that has " << value.str() << " as " << identifier.str() << "in table " << selected_table->get_name() << "." << std::endl;

	return selected_record.str();
}

std::string keilo_server::insert_record(std::string message, size_t pos)
{
	//  ʿ
	/*
	while (message[pos - 1] != '(')
		pos++;

	keilo_record record;
	while (message[pos] != ')') {
		while (message[pos] != ';') {
			std::stringstream identifier;
			while (message[pos] != ':')
				identifier << message[pos++];

			std::stringstream value;
			while (message[pos] != ';')
				value << message[pos++];
			record.push_back(keilo_instance{ identifier.str(), value.str() });
		}
	}*/

	if (!selected_table)
		return "Please select table";

	keilo_record record;

	while (pos < message.length()) {
		std::stringstream identifier;
		while (message[pos] != ':' && pos < message.length())
			identifier << message[pos++];
		pos += 1;

		std::stringstream value;
		while ((message[pos] != ',' && message[pos] != ';') && pos < message.length())
			value << message[pos++];

		record.push_back(keilo_instance{ identifier.str(), value.str() });

		while (message[pos - 1] != ' ' && message[pos - 1] != ','  && message[pos - 1] != ';' && pos < message.length())
			pos++;
	}

	return selected_table->insert(record);
}

std::string keilo_server::update_record(std::string message, size_t pos)
{
	if (!selected_table)
		return "Please select table";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream condition_identifier;
	while (message[pos] != ':' && pos < message.length())
		condition_identifier << message[pos++];
	pos += 1;

	std::stringstream condition_value;
	while (message[pos] != ' '&& pos < message.length())
		condition_value << message[pos++];
	pos += 1;

	std::stringstream new_identifier;
	while (message[pos] != ':'&& pos < message.length())
		new_identifier << message[pos++];
	pos += 1;

	std::stringstream new_value;
	while (message[pos] != ';'&& pos < message.length())
		new_value << message[pos++];
	pos += 1;

	return selected_table->update(keilo_instance{ condition_identifier.str(), condition_value.str() }, keilo_instance{ new_identifier.str(), new_value.str() });
}

std::string keilo_server::remove_record(std::string message, size_t pos)
{
	if (!selected_table)
		return "Please select table";
	if (pos >= message.length())
		return "Syntax error";

	std::stringstream identifier;
	while (message[pos] != ':' && pos < message.length())
		identifier << message[pos++];
	pos += 1;
	std::stringstream value;
	while (message[pos] != ';' && pos < message.length())
		value << message[pos++];

	return selected_table->remove(keilo_instance{ identifier.str(), value.str() });
}
<|endoftext|>


<commit_before>#ifndef FOS_R_H
#define FOS_R_H

// C System-Headers
//
// C++ System headers
//
// Eigen Headers
//
// Boost Headers
//
// Rcpp Headers
#include <Rcpp.h>
// Project Specific Headers
#include "FOS/x_fos.hpp"
#include "Solvers/SubGradientDescent/ISTA/ista.hpp"
#include "Solvers/SubGradientDescent/FISTA/fista.hpp"
#include "Solvers/CoordinateDescent/coordinate_descent.hpp"

template < typename T >
Eigen::Matrix< T, Eigen::Dynamic, 1 > NumVect2Eigen( const Rcpp::NumericVector& vec ) {

    // int len = vec.length();
    //
    // Eigen::Matrix< T, Eigen::Dynamic, 1 > matrixOutput(len);
    //
    // //#pragma omp parallel for
    // for( int j = 0; j < len; j++ ) {
    //     matrixOutput( j ) = static_cast< T >( vec( j ) );
    // }
    //
    // return matrixOutput;

    int len = vec.length();

    T* non_const_vec_data = new T[ len ];
    const T* vec_data = &vec[0];

    std::copy( vec_data, vec_data + len, non_const_vec_data );

    return Eigen::Map< Eigen::Matrix< T, Eigen::Dynamic, 1 > >( non_const_vec_data, len );
}

template < typename T >
Rcpp::NumericVector Eigen2NumVec( const Eigen::Matrix< T, Eigen::Dynamic, 1 >& vec ) {

    // int rows = vec.rows();
    //
    // Rcpp::NumericVector vectorOutput(rows);
    //
    // //#pragma omp parallel for
    // for( int i = 0; i < rows; i++ ) {
    //     vectorOutput( i ) = static_cast<double>( vec( i ) );
    // }
    //
    // return vectorOutput;

    const T* vect_data = vec.data();
    return Rcpp::NumericVector( vect_data, vect_data + vec.size() );
}

template < typename T >
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > NumMat2Eigen( const Rcpp::NumericMatrix& mat ) {
    //
    // int rows = mat.rows();
    // int cols = mat.cols();
    //
    // Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > matrixOutput(rows,cols);
    //
    // //#pragma omp parallel for collapse(2)
    // for( int i = 0; i < rows; i++ ) {
    //     for( int j = 0; j < cols; j++ ) {
    //         matrixOutput( i,j ) = static_cast< T >( mat( i,j ) );
    //     }
    // }
    //
    // return matrixOutput;
    //
    int rows = mat.rows();
    int cols = mat.cols();

    int eigen_mat_size = rows*cols;

    T* non_const_mat_data = new T[ eigen_mat_size ];
    const T* mat_data = &mat[0];

    std::copy( mat_data, mat_data + eigen_mat_size, non_const_mat_data );

    return Eigen::Map< Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> >( non_const_mat_data, rows, cols );

}

template < typename T >
Rcpp::NumericMatrix Eigen2NumMat( const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& mat ) {

    // int rows = mat.rows();
    // int cols = mat.cols();
    //
    // Rcpp::NumericMatrix matrixOutput(rows,cols);
    //
    // //#pragma omp parallel for collapse(2)
    // for( int i=0; i<rows; i++ ) {
    //     for( int j = 0; j < cols; j++ ) {
    //         matrixOutput( i,j ) = static_cast<double>( mat( i,j ) );
    //     }
    // }
    //
    // return matrixOutput;

    const T* mat_data = mat.data();
    return Rcpp::NumericMatrix( mat_data, mat_data + mat_data.size() );
}

// Enable C++11 via this plugin (Rcpp 0.10.3 or later)
// [[Rcpp::plugins(cpp11)]]

// [[Rcpp::export]]
Rcpp::List FOS( const Rcpp::NumericMatrix& X, const Rcpp::NumericVector& Y, const std::string solver_type ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);

    hdim::experimental::X_FOS<double> fos;

    if ( solver_type == "ista" ) {
      fos(  mat_X, vect_Y, hdim::SolverType::ista );
    } else if ( solver_type == "fista" ) {
      fos(  mat_X, vect_Y, hdim::SolverType::fista );
    } else if ( solver_type == "cd" ) {
      fos(  mat_X, vect_Y, hdim::SolverType::cd );
    } else if ( solver_type == "lazy_cd" ) {
      fos(  mat_X, vect_Y, hdim::SolverType::lazy_cd );
    } else {
      fos(  mat_X, vect_Y, hdim::SolverType::ista );
    }

    Rcpp::NumericVector beta = Eigen2NumVec<double>( fos.ReturnCoefficients() );

    beta.attr("names") = Rcpp::colnames(X);

    unsigned int stopping_index = fos.ReturnOptimIndex();
    double lambda = fos.ReturnLambda();
    double intercept = fos.ReturnIntercept();

    Rcpp::NumericVector support = Eigen2NumVec<int>( fos.ReturnSupport() );

    return Rcpp::List::create(Rcpp::Named("beta") = beta,
                              Rcpp::Named("index") = stopping_index,
                              Rcpp::Named("lambda") = lambda,
                              Rcpp::Named("intercept") = intercept,
                              Rcpp::Named("support") = support);

}

// [[Rcpp::export]]
Rcpp::NumericVector CoordinateDescent( Rcpp::NumericMatrix X,
                        Rcpp::NumericVector Y,
                        Rcpp::NumericVector Beta_0,
                        double lambda,
                        unsigned int num_iterations ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::CoordinateDescentSolver<double> cd_solver( mat_X, vect_Y, vect_Beta_0 );

    return Eigen2NumVec<double>( cd_solver( mat_X, vect_Y, vect_Beta_0, lambda, num_iterations ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector CoordinateDescent_DG( Rcpp::NumericMatrix X,
                        Rcpp::NumericVector Y,
                        Rcpp::NumericVector Beta_0,
                        double lambda,
                        double duality_gap_target ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::CoordinateDescentSolver<double> cd_solver( mat_X, vect_Y, vect_Beta_0 );

    return Eigen2NumVec<double>( cd_solver( mat_X, vect_Y, vect_Beta_0, lambda, static_cast<double>( duality_gap_target ) ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector ISTA( Rcpp::NumericMatrix X,
                          Rcpp::NumericVector Y,
                          Rcpp::NumericVector Beta_0,
                          double lambda,
                          unsigned int num_iterations,
                          double L_0 = 0.1 ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::ISTA<double> ista_solver( static_cast<double>( L_0 ) );

    return Eigen2NumVec<double>( ista_solver( mat_X, vect_Y, vect_Beta_0, lambda, num_iterations ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector ISTA_DG( Rcpp::NumericMatrix X,
                          Rcpp::NumericVector Y,
                          Rcpp::NumericVector Beta_0,
                          double lambda,
                          double duality_gap_target,
                          double L_0 = 0.1 ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::ISTA<double> ista_solver( static_cast<double>( L_0 ) );

    return Eigen2NumVec<double>( ista_solver( mat_X, vect_Y, vect_Beta_0, lambda, static_cast<double>( duality_gap_target ) ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector FISTA( Rcpp::NumericMatrix X,
                           Rcpp::NumericVector Y,
                           Rcpp::NumericVector Beta_0,
                           double lambda,
                           unsigned int num_iterations,
                           double L_0 = 0.1 ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::ISTA<double> fista_solver( static_cast<double>( L_0 ) );

    return Eigen2NumVec<double>( fista_solver( mat_X, vect_Y, vect_Beta_0, lambda, num_iterations ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector FISTA_DG( Rcpp::NumericMatrix X,
                          Rcpp::NumericVector Y,
                          Rcpp::NumericVector Beta_0,
                          double lambda,
                          double duality_gap_target,
                          double L_0 = 0.1 ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::FISTA<double> fista_solver( static_cast<double>( L_0 ) );

    return Eigen2NumVec<double>( fista_solver( mat_X, vect_Y, vect_Beta_0, lambda, static_cast<double>( duality_gap_target ) ) );
}

#endif // FOS_R_H
<commit_msg>Modified R Wrapper to allow use of single-precision floating point types<commit_after>#ifndef FOS_R_H
#define FOS_R_H

// C System-Headers
//
// C++ System headers
#include <type_traits>
// Eigen Headers
//
// Boost Headers
//
// Rcpp Headers
#include <Rcpp.h>
// Project Specific Headers
#include "FOS/x_fos.hpp"
#include "Solvers/SubGradientDescent/ISTA/ista.hpp"
#include "Solvers/SubGradientDescent/FISTA/fista.hpp"
#include "Solvers/CoordinateDescent/coordinate_descent.hpp"

template < typename T >
Eigen::Matrix< T, Eigen::Dynamic, 1 > NumVect2Eigen( const Rcpp::NumericVector& vec ) {

    int len = vec.length();

    T* non_const_vec_data = new T[ len ];
    const double* vec_data = &vec[0];

    std::copy( vec_data, vec_data + len, non_const_vec_data );

    return Eigen::Map< Eigen::Matrix< T, Eigen::Dynamic, 1 > >( non_const_vec_data, len );
}

template < typename T >
Rcpp::NumericVector Eigen2NumVec( const Eigen::Matrix< T, Eigen::Dynamic, 1 >& vec ) {

    const T* vect_data = vec.data();
    return Rcpp::NumericVector::import( vect_data, vect_data + vec.size() );
}

template < typename T >
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > NumMat2Eigen( const Rcpp::NumericMatrix& mat ) {

    int rows = mat.rows();
    int cols = mat.cols();

    int eigen_mat_size = rows*cols;

    T* non_const_mat_data = new T[ eigen_mat_size ];
    const double* mat_data = &mat[0];

    std::copy( mat_data, mat_data + eigen_mat_size, non_const_mat_data );

    return Eigen::Map< Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> >( non_const_mat_data, rows, cols );

}

template < typename T >
Rcpp::NumericMatrix Eigen2NumMat( const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic >& mat ) {

    const T* mat_data = mat.data();
    return Rcpp::NumericMatrix::import( mat_data, mat_data + mat_data.size() );
}

// Enable C++11 via this plugin (Rcpp 0.10.3 or later)
// [[Rcpp::plugins(cpp11)]]

// [[Rcpp::export]]
Rcpp::List FOS( const Rcpp::NumericMatrix& X, const Rcpp::NumericVector& Y, const std::string solver_type ) {

    // Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    // Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    //
    // hdim::experimental::X_FOS<double> fos;

    Eigen::MatrixXf mat_X = NumMat2Eigen<float>(X);
    Eigen::VectorXf vect_Y = NumVect2Eigen<float>(Y);

    hdim::experimental::X_FOS<float> fos;

    if ( solver_type == "ista" ) {
      fos(  mat_X, vect_Y, hdim::SolverType::ista );
    } else if ( solver_type == "fista" ) {
      fos(  mat_X, vect_Y, hdim::SolverType::fista );
    } else if ( solver_type == "cd" ) {
      fos(  mat_X, vect_Y, hdim::SolverType::cd );
    } else if ( solver_type == "lazy_cd" ) {
      fos(  mat_X, vect_Y, hdim::SolverType::lazy_cd );
    } else {
      fos(  mat_X, vect_Y, hdim::SolverType::ista );
    }

    // Rcpp::NumericVector beta = Eigen2NumVec<double>( fos.ReturnCoefficients() );

    Rcpp::NumericVector beta = Eigen2NumVec<float>( fos.ReturnCoefficients() );

    beta.attr("names") = Rcpp::colnames(X);

    unsigned int stopping_index = fos.ReturnOptimIndex();
    double lambda = fos.ReturnLambda();
    double intercept = fos.ReturnIntercept();

    Rcpp::NumericVector support = Eigen2NumVec<int>( fos.ReturnSupport() );

    return Rcpp::List::create( Rcpp::Named("beta") = beta,
                              Rcpp::Named("index") = stopping_index,
                              Rcpp::Named("lambda") = lambda,
                              Rcpp::Named("intercept") = intercept,
                              Rcpp::Named("support") = support );

}

// [[Rcpp::export]]
Rcpp::NumericVector CoordinateDescent( Rcpp::NumericMatrix X,
                        Rcpp::NumericVector Y,
                        Rcpp::NumericVector Beta_0,
                        double lambda,
                        unsigned int num_iterations ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::CoordinateDescentSolver<double> cd_solver( mat_X, vect_Y, vect_Beta_0 );

    return Eigen2NumVec<double>( cd_solver( mat_X, vect_Y, vect_Beta_0, lambda, num_iterations ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector CoordinateDescent_DG( Rcpp::NumericMatrix X,
                        Rcpp::NumericVector Y,
                        Rcpp::NumericVector Beta_0,
                        double lambda,
                        double duality_gap_target ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::CoordinateDescentSolver<double> cd_solver( mat_X, vect_Y, vect_Beta_0 );

    return Eigen2NumVec<double>( cd_solver( mat_X, vect_Y, vect_Beta_0, lambda, static_cast<double>( duality_gap_target ) ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector ISTA( Rcpp::NumericMatrix X,
                          Rcpp::NumericVector Y,
                          Rcpp::NumericVector Beta_0,
                          double lambda,
                          unsigned int num_iterations,
                          double L_0 = 0.1 ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::ISTA<double> ista_solver( static_cast<double>( L_0 ) );

    return Eigen2NumVec<double>( ista_solver( mat_X, vect_Y, vect_Beta_0, lambda, num_iterations ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector ISTA_DG( Rcpp::NumericMatrix X,
                          Rcpp::NumericVector Y,
                          Rcpp::NumericVector Beta_0,
                          double lambda,
                          double duality_gap_target,
                          double L_0 = 0.1 ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::ISTA<double> ista_solver( static_cast<double>( L_0 ) );

    return Eigen2NumVec<double>( ista_solver( mat_X, vect_Y, vect_Beta_0, lambda, static_cast<double>( duality_gap_target ) ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector FISTA( Rcpp::NumericMatrix X,
                           Rcpp::NumericVector Y,
                           Rcpp::NumericVector Beta_0,
                           double lambda,
                           unsigned int num_iterations,
                           double L_0 = 0.1 ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::ISTA<double> fista_solver( static_cast<double>( L_0 ) );

    return Eigen2NumVec<double>( fista_solver( mat_X, vect_Y, vect_Beta_0, lambda, num_iterations ) );
}

// [[Rcpp::export]]
Rcpp::NumericVector FISTA_DG( Rcpp::NumericMatrix X,
                          Rcpp::NumericVector Y,
                          Rcpp::NumericVector Beta_0,
                          double lambda,
                          double duality_gap_target,
                          double L_0 = 0.1 ) {

    Eigen::MatrixXd mat_X = NumMat2Eigen<double>(X);
    Eigen::VectorXd vect_Y = NumVect2Eigen<double>(Y);
    Eigen::VectorXd vect_Beta_0 = NumVect2Eigen<double>(Beta_0);

    hdim::FISTA<double> fista_solver( static_cast<double>( L_0 ) );

    return Eigen2NumVec<double>( fista_solver( mat_X, vect_Y, vect_Beta_0, lambda, static_cast<double>( duality_gap_target ) ) );
}

#endif // FOS_R_H
<|endoftext|>