Azure-Kinect-Sensor-SDK/tools/k4arecorder/cmdparser.h

161 строка
4.3 KiB
C++

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef CMDPARSER_H
#define CMDPARSER_H
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <utility>
#include <functional>
namespace CmdParser
{
typedef std::function<void(const std::vector<char *> &)> OptionHandlerFunc;
typedef std::function<void()> VoidHandlerFunc;
class ArgumentError : public std::runtime_error
{
public:
ArgumentError(const std::string option, const std::string message) :
std::runtime_error(message),
m_option(option),
m_message(message)
{
}
const std::string option() const
{
return m_option;
}
private:
const std::string m_option, m_message;
};
class OptionParser
{
public:
OptionParser() {}
void RegisterOption(std::string option_list, std::string description, int arg_count, OptionHandlerFunc &&handler)
{
std::istringstream split(option_list);
std::ostringstream options_str;
std::string option;
bool first = true;
while (std::getline(split, option, '|'))
{
m_cmd_options[option] = OptionHandler{ arg_count, handler };
if (first)
{
options_str << option;
first = false;
}
else
{
options_str << ", " << option;
}
}
m_cmd_usage.push_back(std::make_pair(options_str.str(), description));
}
void RegisterOption(std::string option_list, std::string description, VoidHandlerFunc &&handler)
{
RegisterOption(option_list, description, 0, [handler](const std::vector<char *> &) { handler(); });
}
void PrintOptions()
{
std::cout << " Options:" << std::endl;
size_t max_options_length = 0;
for (std::pair<std::string, std::string> usage : m_cmd_usage)
{
if (usage.first.length() > max_options_length)
max_options_length = usage.first.length();
}
for (std::pair<std::string, std::string> usage : m_cmd_usage)
{
std::cout << " " << usage.first << std::string(max_options_length - usage.first.length() + 2, ' ');
std::istringstream split(usage.second);
std::string line;
bool first = true;
while (std::getline(split, line))
{
if (first)
{
std::cout << line << std::endl;
first = false;
}
else
{
std::cout << " " << std::string(max_options_length + 4, ' ') << line << std::endl;
}
}
}
}
/** Parse the command line arguments, and run the handler for each.
*
* Returns the number of remaining arguments after parsing.
* May throw ArgumentError if a handler fails.
*/
int ParseCmd(int argc, char **argv)
{
if (argc < 2)
return 0;
for (int i = 1; i < argc; i++)
{
std::string option = argv[i];
if (m_cmd_options.count(option) == 0)
return argc - i;
const OptionHandler &handler = m_cmd_options[option];
std::vector<char *> args;
if (i + handler.arg_count < argc)
{
for (int j = 0; j < handler.arg_count; j++)
{
args.push_back(argv[i + j + 1]);
}
try
{
handler.handler(args);
}
catch (ArgumentError &)
{
throw;
}
catch (std::exception &e)
{
throw ArgumentError(option, e.what());
}
i += handler.arg_count;
}
else
{
return argc - i - 1;
}
}
return 0;
}
private:
struct OptionHandler
{
int arg_count;
OptionHandlerFunc handler;
};
std::map<std::string, OptionHandler> m_cmd_options;
std::vector<std::pair<std::string, std::string>> m_cmd_usage;
};
} // namespace CmdParser
#endif /* CMDPARSER_H */