Skip to content

Commit

Permalink
Refactored ArgumentParser to use CLI11
Browse files Browse the repository at this point in the history
This also fixes a crashdump when calling jpscore without parameter and
no ini.xml in current working dir.
  • Loading branch information
Ozaq committed Sep 18, 2019
1 parent dbc8af5 commit 330903b
Show file tree
Hide file tree
Showing 18 changed files with 159 additions and 212 deletions.
Empty file removed .gitmodules
Empty file.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ find_package(fmt 6.0 REQUIRED CONFIG)
# spdlog
find_package(spdlog 1.3 REQUIRED CONFIG)

# CLI11
find_package(CLI11 1.8 REQUIRED CONFIG)

# CMakes find_pacakge has no support for generator expressions hence we have to
# do this the hard way
if(${CMAKE_SYSTEM} MATCHES "Darwin")
Expand Down Expand Up @@ -509,6 +512,7 @@ target_link_libraries(core
poly2tri
tinyxml
visilibity
CLI11::CLI11
$<$<BOOL:${AIROUTER}>:CGAL::CGAL>
$<$<BOOL:${JPSFIRE}>:cnpy>
fs
Expand Down
1 change: 0 additions & 1 deletion Simulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#ifndef SIMULATION_H_
#define SIMULATION_H_

#include "general/ArgumentParser.h"
#include "geometry/Building.h"
#include "geometry/SubRoom.h"
#include "IO/OutputHandler.h"
Expand Down
2 changes: 1 addition & 1 deletion events/EventManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ bool EventManager::DisseminateKnowledge(Building* _b)

bool EventManager::UpdateRoute(Pedestrian* ped)
{
//create the key as string.
//create the key as std::string.
//map are sorted by default
std::string key= ped->GetKnowledgeAsString();
// std::cout << "key: <" << key << ">" << std::endl;
Expand Down
134 changes: 20 additions & 114 deletions general/ArgumentParser.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/**
* \file ArgumentParser.cpp
* \date Apr 20, 2009
* \version v0.8
* \copyright <2009-2018> Forschungszentrum Jülich GmbH. All rights reserved.
* \copyright <2009-2019> Forschungszentrum Jülich GmbH. All rights reserved.
*
* \section License
* This file is part of JuPedSim.
Expand All @@ -19,130 +17,38 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with JuPedSim. If not, see <http://www.gnu.org/licenses/>.
*
* \section Description
*
*
**/
#include "ArgumentParser.h"

#include "general/OpenMP.h"
#include "general/Logger.h"
#include "IO/IniFileParser.h"
#include "IO/OutputHandler.h"
#include "general/Logger.h"
#include "general/OpenMP.h"
#include "pedestrian/AgentsParameters.h"
#include "routing/global_shortest/GlobalRouter.h"
#include "routing/quickest/QuickestPathRouter.h"
#include "routing/smoke_router/SmokeRouter.h"

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>

void ArgumentParser::Usage(const std::string file)
{
fprintf(stderr, "Usages: \n");
fprintf(stderr, " %s <path to file> start the simulation with the specified file.\n", file.c_str());
fprintf(stderr, " %s search and use the file ini.xml in the current directory.\n",
file.c_str());
fprintf(stderr, " %s -h/--help display this text.\n", file.c_str());
#ifdef _JPS_AS_A_SERVICE
fprintf(stderr, " %s --as-a-service -p <port nr> runs jps as a service at port <port nr>.\n", file.c_str());
#endif
exit(EXIT_SUCCESS);
}

ArgumentParser::ArgumentParser(Configuration* config)
const fs::path & ArgumentParser::IniFilePath() const
{
_config = config;
return iniFilePath;
}

ArgumentParser::~ArgumentParser(){}

bool ArgumentParser::ParseArgs(int argc, char** argv)
std::tuple<ArgumentParser::Execution, int> ArgumentParser::Parse(int argc, char * argv[])
{
//special case of the default configuration ini.xml
if (argc==1) {
Logging::Info("Trying to load the default configuration from the file <ini.xml>");

IniFileParser* p = new IniFileParser(_config);
if (!p->Parse("ini.xml")) {
Usage(argv[0]);
}
return true;
}

std::string argument = argv[1];

if (argument=="-h" || argument=="--help") {
Usage(argv[0]);
return false;
}

// other special case where a single configuration file is submitted
//check if inifile options are given
if (argc==2) {
std::string prefix1 = "--ini=";
std::string prefix2 = "--inifile=";

if (!argument.compare(0, prefix2.size(), prefix2)) {
argument.erase(0, prefix2.size());
}
else if (!argument.compare(0, prefix1.size(), prefix1)) {
argument.erase(0, prefix1.size());
}
IniFileParser* p = new IniFileParser(_config);
bool status = p->Parse(argument);
delete p;
return status;
}

#ifdef _JPS_AS_A_SERVICE //TODO try to avoid macros!
if (argc==4 || argc==6) {

std::string argument1 = argv[1];
if (argument1=="--as-a-service") { //runs jps as a service
std::string argument2 = argv[2];
if (argument2=="-p") { //port
std::string argument3 = argv[3]; //port number at which jps is listening
int port = std::atoi(argument3.c_str());
_config->SetRunAsService(true);
_config->SetServicePort(port);
if (argc==6) {
std::string argument4 = argv[4];
std::string argument5 = argv[5];
if (argument4=="--dump-scenario") {
struct stat sb;
if (stat(argument5.c_str(), &sb)==0 && S_ISDIR(sb.st_mode)) {
if (*(argument5.end()-1)!='/') {
argument5.append("/");
}
_config->SetProjectRootDir(argument5);
_config->SetGeometryFile("geo.xml");
_config->SetProjectFile("ini.xml");
_config->SetTrajectoriesFile(_config->GetProjectRootDir() / "tra.xml");
_config->SetFileFormat(FileFormat::FORMAT_XML_PLAIN);
_config->SetFps(25);
_config->SetDumpScenario(true);
return true;
}
else {
std::cerr << "unable to write to: " << argument5 << std::endl;
return false;
}
}
}
else {
return true;
}
}

}
}
#endif

//more than one argument was supplied
Usage(argv[0]);
return false;
try {
app.parse(argc, argv);
// Silence warnigns about iniFilePathOpt declared as member but never
// used. iniFilePathOpt is a member to keep the declaration of all
// options in the header file. If there was no iniFilePathOpt member the
// add_option(...) call would need to be done the constructor.
(void) iniFilePathOpt;
if(auto msg = CLI::ExistingFile(iniFilePath.string()); !msg.empty()) {
throw CLI::ValidationError(msg);
}
} catch(const CLI::ParseError & e) {
return {Execution::ABORT, app.exit(e)};
}
return {Execution::CONTINUE, 0};
}
64 changes: 32 additions & 32 deletions general/ArgumentParser.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/**
* \file ArgumentParser.h
* \date Apr 20, 2009
* \version v0.7
* \copyright <2009-2015> Forschungszentrum Jülich GmbH. All rights reserved.
* \copyright <2009-2019> Forschungszentrum Jülich GmbH. All rights reserved.
*
* \section License
* This file is part of JuPedSim.
Expand All @@ -21,43 +19,45 @@
* along with JuPedSim. If not, see <http://www.gnu.org/licenses/>.
*
* \section Description
*
* A simple wrapper around CLI11 argument parsing
*
**/
#pragma once

#include "Macros.h"
#include "Configuration.h"
#include "general/Filesystem.h"

#include "math/ODESolver.h"
#include "math/OperationalModel.h"
#include "routing/DirectionStrategy.h"
#include "routing/RoutingEngine.h"
#include <CLI/CLI.hpp>

#ifdef _HYBRID_SIMULATION
#include "hybrid/HybridSimulationManager.h"
#endif
#include <tuple>

#include <cstdlib>
#include <map>
#include <memory>
#include <string>
#include <vector>
class ArgumentParser final {
private:
fs::path iniFilePath{"ini.xml"};
CLI::App app{"JuPedSim"};
CLI::Option* iniFilePathOpt = app.add_option(
"inifile", iniFilePath, "Path to your inifile");

class OutputHandler;
public:
enum class Execution {
CONTINUE,
ABORT
};

extern OutputHandler* Log;
/// @return inifile argument. If none was parsed this defaults to 'ini.xml'
const fs::path& IniFilePath() const;

class ArgumentParser {
void Usage(const std::string file);
Configuration* _config;
public:
// constructor
ArgumentParser(Configuration* config);
~ArgumentParser();
/**
* Parse the commands passed to the command line
* specially looks for the initialization file
*/
bool ParseArgs(int argc, char** argv);
/// Parses command line arguments
/// Parsing ends in one of three states:
/// 1) Everything parsed, all ok -> returns [CONTINUE, 0]
/// 2) Error during parsing, e.g. inifile does not exist
/// -> [ABORT, EXIT_FAILURE]
/// 3) Parsed -h/--help, not an error but execution should end
/// -> [ABORT, EXIT_SUCCESS]
///
/// @param argc argument count
/// @param argv arguments
/// @return [Execution, ReturnCode] state after parsing. Excution describes
/// if the program shall continue or abort. In case 'Execution' is
/// ABORT returncode contains the to-be-used returncode.
std::tuple<Execution, int> Parse(int argc, char* argv[]);
};
Loading

0 comments on commit 330903b

Please sign in to comment.