extract ParametersParser to it's own file

This commit is contained in:
Maxime Coste 2012-12-07 14:27:10 +01:00
parent d25bafa95d
commit 158f5a5c84
3 changed files with 222 additions and 182 deletions

View File

@ -17,6 +17,7 @@
#include "event_manager.hh"
#include "color_registry.hh"
#include "client_manager.hh"
#include "parameters_parser.hh"
#include <sys/types.h>
#include <sys/stat.h>
@ -38,188 +39,6 @@ struct wrong_argument_count : runtime_error
wrong_argument_count() : runtime_error("wrong argument count") {}
};
struct unknown_option : public runtime_error
{
unknown_option(const String& name)
: runtime_error("unknown option '" + name + "'") {}
};
struct missing_option_value: public runtime_error
{
missing_option_value(const String& name)
: runtime_error("missing value for option '" + name + "'") {}
};
// ParameterParser provides tools to parse command parameters.
// There are 3 types of parameters:
// * unnamed options, which are accessed by position (ignoring named ones)
// * named boolean options, which are enabled using '-name' syntax
// * named string options, which are defined using '-name value' syntax
struct ParametersParser
{
// the options defines named options, if they map to true, then
// they are understood as string options, else they are understood as
// boolean option.
ParametersParser(const CommandParameters& params,
std::unordered_map<String, bool> options)
: m_params(params), m_positional(params.size(), true), m_options(options)
{
for (size_t i = 0; i < params.size(); ++i)
{
if (params[i][0] == '-')
{
auto it = options.find(params[i].substr(1_byte));
if (it == options.end())
throw unknown_option(params[i]);
if (it->second)
{
if (i + 1 == params.size() or params[i+1][0] == '-')
throw missing_option_value(params[i]);
m_positional[i+1] = false;
}
m_positional[i] = false;
}
// all options following -- are positional
if (params[i] == "--")
break;
}
}
// check if a named option (either string or boolean) is specified
bool has_option(const String& name) const
{
assert(m_options.find(name) != m_options.end());
for (auto& param : m_params)
{
if (param[0] == '-' and param.substr(1_byte) == name)
return true;
if (param == "--")
break;
}
return false;
}
// get a string option value, returns an empty string if the option
// is not defined
const String& option_value(const String& name) const
{
auto it = m_options.find(name);
assert(it != m_options.end());
assert(it->second == true);
for (size_t i = 0; i < m_params.size(); ++i)
{
if (m_params[i][0] == '-' and m_params[i].substr(1_byte) == name)
return m_params[i+1];
if (m_params[i] == "--")
break;
}
static String empty;
return empty;
}
size_t positional_count() const
{
size_t res = 0;
for (bool positional : m_positional)
{
if (positional)
++res;
}
return res;
}
struct iterator
{
public:
typedef String value_type;
typedef const value_type* pointer;
typedef const value_type& reference;
typedef size_t difference_type;
typedef std::forward_iterator_tag iterator_category;
iterator(const ParametersParser& parser, size_t index)
: m_parser(parser), m_index(index) {}
const String& operator*() const
{
assert(m_parser.m_positional[m_index]);
return m_parser.m_params[m_index];
}
const String* operator->() const
{
assert(m_parser.m_positional[m_index]);
return &m_parser.m_params[m_index];
}
iterator& operator++()
{
while (m_index < m_parser.m_positional.size() and
not m_parser.m_positional[++m_index]) {}
return *this;
}
bool operator==(const iterator& other) const
{
return &m_parser == &other.m_parser and m_index == other.m_index;
}
bool operator!=(const iterator& other) const
{
return &m_parser != &other.m_parser or m_index != other.m_index;
}
bool operator<(const iterator& other) const
{
assert(&m_parser == &other.m_parser);
return m_index < other.m_index;
}
private:
const ParametersParser& m_parser;
size_t m_index;
};
// positional parameter begin
iterator begin() const
{
int index = 0;
while (index < m_positional.size() and not m_positional[index])
++index;
return iterator(*this, index);
}
// positional parameter end
iterator end() const
{
return iterator(*this, m_params.size());
}
// access positional parameter by index
const String& operator[] (size_t index) const
{
assert(index < positional_count());
iterator it = begin();
while (index)
{
++it;
--index;
}
return *it;
}
private:
const CommandParameters& m_params;
std::vector<bool> m_positional;
std::unordered_map<String, bool> m_options;
};
Buffer* open_or_create(const String& filename, Context& context)
{
Buffer* buffer = create_buffer_from_file(filename);

103
src/parameters_parser.cc Normal file
View File

@ -0,0 +1,103 @@
#include "parameters_parser.hh"
namespace Kakoune
{
ParametersParser::ParametersParser(const ParameterList& params,
std::unordered_map<String, bool> options)
: m_params(params), m_positional(params.size(), true),
m_options(std::move(options))
{
for (size_t i = 0; i < params.size(); ++i)
{
if (params[i][0] == '-')
{
auto it = m_options.find(params[i].substr(1_byte));
if (it == m_options.end())
throw unknown_option(params[i]);
if (it->second)
{
if (i + 1 == params.size() or params[i+1][0] == '-')
throw missing_option_value(params[i]);
m_positional[i+1] = false;
}
m_positional[i] = false;
}
// all options following -- are positional
if (params[i] == "--")
break;
}
}
bool ParametersParser::has_option(const String& name) const
{
assert(m_options.find(name) != m_options.end());
for (auto& param : m_params)
{
if (param[0] == '-' and param.substr(1_byte) == name)
return true;
if (param == "--")
break;
}
return false;
}
const String& ParametersParser::option_value(const String& name) const
{
auto it = m_options.find(name);
assert(it != m_options.end());
assert(it->second == true);
for (size_t i = 0; i < m_params.size(); ++i)
{
if (m_params[i][0] == '-' and m_params[i].substr(1_byte) == name)
return m_params[i+1];
if (m_params[i] == "--")
break;
}
static String empty;
return empty;
}
size_t ParametersParser::positional_count() const
{
size_t res = 0;
for (bool positional : m_positional)
{
if (positional)
++res;
}
return res;
}
const String& ParametersParser::operator[] (size_t index) const
{
assert(index < positional_count());
iterator it = begin();
while (index)
{
++it;
--index;
}
return *it;
}
ParametersParser::iterator ParametersParser::begin() const
{
int index = 0;
while (index < m_positional.size() and not m_positional[index])
++index;
return iterator(*this, index);
}
ParametersParser::iterator ParametersParser::end() const
{
return iterator(*this, m_params.size());
}
}

118
src/parameters_parser.hh Normal file
View File

@ -0,0 +1,118 @@
#ifndef parameters_parser_hh_INCLUDED
#define parameters_parser_hh_INCLUDED
#include "string.hh"
#include "memoryview.hh"
#include "exception.hh"
#include <unordered_map>
namespace Kakoune
{
using ParameterList = memoryview<String>;
struct unknown_option : public runtime_error
{
unknown_option(const String& name)
: runtime_error("unknown option '" + name + "'") {}
};
struct missing_option_value: public runtime_error
{
missing_option_value(const String& name)
: runtime_error("missing value for option '" + name + "'") {}
};
// ParameterParser provides tools to parse command parameters.
// There are 3 types of parameters:
// * unnamed options, which are accessed by position (ignoring named ones)
// * named boolean options, which are enabled using '-name' syntax
// * named string options, which are defined using '-name value' syntax
struct ParametersParser
{
// the options defines named options, if they map to true, then
// they are understood as string options, else they are understood as
// boolean option.
ParametersParser(const ParameterList& params,
std::unordered_map<String, bool> options);
// check if a named option (either string or boolean) is specified
bool has_option(const String& name) const;
// get a string option value, returns an empty string if the option
// is not defined
const String& option_value(const String& name) const;
// positional parameters count
size_t positional_count() const;
struct iterator
{
public:
typedef String value_type;
typedef const value_type* pointer;
typedef const value_type& reference;
typedef size_t difference_type;
typedef std::forward_iterator_tag iterator_category;
iterator(const ParametersParser& parser, size_t index)
: m_parser(parser), m_index(index) {}
const String& operator*() const
{
assert(m_parser.m_positional[m_index]);
return m_parser.m_params[m_index];
}
const String* operator->() const
{
assert(m_parser.m_positional[m_index]);
return &m_parser.m_params[m_index];
}
iterator& operator++()
{
while (m_index < m_parser.m_positional.size() and
not m_parser.m_positional[++m_index]) {}
return *this;
}
bool operator==(const iterator& other) const
{
return &m_parser == &other.m_parser and m_index == other.m_index;
}
bool operator!=(const iterator& other) const
{
return &m_parser != &other.m_parser or m_index != other.m_index;
}
bool operator<(const iterator& other) const
{
assert(&m_parser == &other.m_parser);
return m_index < other.m_index;
}
private:
const ParametersParser& m_parser;
size_t m_index;
};
// access positional parameter by index
const String& operator[] (size_t index) const;
// positional parameter begin
iterator begin() const;
// positional parameter end
iterator end() const;
private:
ParameterList m_params;
std::vector<bool> m_positional;
std::unordered_map<String, bool> m_options;
};
}
#endif // parameters_parser_hh_INCLUDED