Skip to content
Open

Raii #14

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmdparser.Test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
set(SOURCE_FILES TestMain.cpp catch.hpp tests.cpp)
add_executable(cmdparserTest ${SOURCE_FILES})
add_executable(sample sample.cpp)
IF(APPLE)
TARGET_COMPILE_OPTIONS(cmdparserTest PUBLIC INTERFACE "-stdlib=libc++")
ENDIF(APPLE)
15 changes: 15 additions & 0 deletions cmdparser.Test/sample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Created by marcel on 12/21/17.
//

#include <iostream>
#include "../cmdparser.hpp"

int main(int argc, char**argv)
{
cli::Parser parser(argc, argv);
parser.disable_help();
const auto value = parser.run(std::cout, std::cerr);

return 0;
}
2 changes: 1 addition & 1 deletion cmdparser.Test/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
Copyright (c) 2015 - 2016 Florian Rappl
*/

#include "catch.hpp"
#include <sstream>
#include "../cmdparser.hpp"
#include "catch.hpp"

using namespace cli;

Expand Down
59 changes: 32 additions & 27 deletions cmdparser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
#include <string>
#include <vector>
#include <sstream>
#include <memory>
#include <functional>

namespace cli {
class NormalExitFromCallback : std::exception{

};
/// Class used to wrap integer types to specify desired numerical base for specific argument parsing
template <typename T, int numericalBase = 0> class NumericalBase {
public:
Expand Down Expand Up @@ -106,7 +110,11 @@ namespace cli {
CallbackArgs args { arguments, output, error };
value = callback(args);
return true;
} catch (...) {
}
catch(NormalExitFromCallback const&){
return false;// should this return "true"?
}
catch (...) {
return false;
}
}
Expand All @@ -130,7 +138,11 @@ namespace cli {
try {
value = Parser::parse(arguments, value);
return true;
} catch (...) {
}
catch(NormalExitFromCallback const&){
return true;
}
catch (...) {
return false;
}
}
Expand Down Expand Up @@ -277,14 +289,8 @@ namespace cli {
enable_help();
}

~Parser() {
for (int i = 0, n = _commands.size(); i < n; ++i) {
delete _commands[i];
}
}

bool has_help() const {
for (const auto command : _commands) {
for (const auto &command : _commands) {
if (command->name == "h" && command->alternative == "--help") {
return true;
}
Expand All @@ -296,7 +302,7 @@ namespace cli {
void enable_help() {
set_callback("h", "help", std::function<bool(CallbackArgs&)>([this](CallbackArgs& args){
args.output << this->usage();
exit(0);
throw NormalExitFromCallback();
return false;
}), "", true);
}
Expand All @@ -318,27 +324,26 @@ namespace cli {

template<typename T>
void set_required(const std::string& name, const std::string& alternative, const std::string& description = "", bool dominant = false) {
auto command = new CmdArgument<T> { name, alternative, description, true, dominant };
_commands.push_back(command);
_commands.emplace_back(new CmdArgument<T> { name, alternative, description, true, dominant });
}

template<typename T>
void set_optional(const std::string& name, const std::string& alternative, T defaultValue, const std::string& description = "", bool dominant = false) {
auto command = new CmdArgument<T> { name, alternative, description, false, dominant };
command->value = defaultValue;
_commands.push_back(command);
_commands.emplace_back(command);
}

template<typename T>
void set_callback(const std::string& name, const std::string& alternative, std::function<T(CallbackArgs&)> callback, const std::string& description = "", bool dominant = false) {
auto command = new CmdFunction<T> { name, alternative, description, false, dominant };
command->callback = callback;
_commands.push_back(command);
_commands.emplace_back(command);
}

inline void run_and_exit_if_error() {
if (run() == false) {
exit(1);
throw std::runtime_error("");
}
}

Expand Down Expand Up @@ -380,25 +385,25 @@ namespace cli {

// First, parse dominant arguments since they succeed even if required
// arguments are missing.
for (auto command : _commands) {
for (auto &command : _commands) {
if (command->handled && command->dominant && !command->parse(output, error)) {
error << howto_use(command);
error << howto_use(command.get());
return false;
}
}

// Next, check for any missing arguments.
for (auto command : _commands) {
for (auto &command : _commands) {
if (command->required && !command->handled) {
error << howto_required(command);
error << howto_required(command.get());
return false;
}
}

// Finally, parse all remaining arguments.
for (auto command : _commands) {
for (auto &command : _commands) {
if (command->handled && !command->dominant && !command->parse(output, error)) {
error << howto_use(command);
error << howto_use(command.get());
return false;
}
}
Expand All @@ -410,7 +415,7 @@ namespace cli {
T get(const std::string& name) const {
for (const auto& command : _commands) {
if (command->name == name) {
auto cmd = dynamic_cast<CmdArgument<T>*>(command);
auto cmd = dynamic_cast<CmdArgument<T>*>(command.get());

if (cmd == nullptr) {
throw std::runtime_error("Invalid usage of the parameter " + name + " detected.");
Expand Down Expand Up @@ -451,19 +456,19 @@ namespace cli {

protected:
CmdBase* find(const std::string& name) {
for (auto command : _commands) {
for (auto &command : _commands) {
if (command->is(name)) {
return command;
return command.get();
}
}

return nullptr;
}

CmdBase* find_default() {
for (auto command : _commands) {
for (auto &command : _commands) {
if (command->name == "") {
return command;
return command.get();
}
}

Expand Down Expand Up @@ -526,6 +531,6 @@ namespace cli {
private:
const std::string _appname;
std::vector<std::string> _arguments;
std::vector<CmdBase*> _commands;
std::vector<std::unique_ptr<CmdBase>> _commands;
};
}