settings: configuration file processing rewrite
This commit is contained in:
@@ -68,13 +68,13 @@ bool LocaleBasedItemSorting::operator()(const MPD::Item &a, const MPD::Item &b)
|
||||
case MPD::itSong:
|
||||
switch (m_sort_mode)
|
||||
{
|
||||
case smName:
|
||||
case SortMode::Name:
|
||||
result = m_cmp(*a.song, *b.song);
|
||||
break;
|
||||
case smMTime:
|
||||
case SortMode::ModificationTime:
|
||||
result = a.song->getMTime() > b.song->getMTime();
|
||||
break;
|
||||
case smCustomFormat:
|
||||
case SortMode::CustomFormat:
|
||||
result = m_cmp(a.song->toString(Config.browser_sort_format, Config.tags_separator),
|
||||
b.song->toString(Config.browser_sort_format, Config.tags_separator));
|
||||
break;
|
||||
|
||||
@@ -18,10 +18,14 @@
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef NCMPCPP_UTILITY_CONVERSION_H
|
||||
#define NCMPCPP_UTILITY_CONVERSION_H
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/type_traits/is_unsigned.hpp>
|
||||
|
||||
#include "config.h"
|
||||
#include "gcc.h"
|
||||
|
||||
struct ConversionError
|
||||
@@ -35,7 +39,7 @@ private:
|
||||
std::string m_source_value;
|
||||
};
|
||||
|
||||
struct OutOfBounds
|
||||
struct OutOfBounds : std::exception
|
||||
{
|
||||
const std::string &errorMessage() { return m_error_message; }
|
||||
|
||||
@@ -43,23 +47,25 @@ struct OutOfBounds
|
||||
GNUC_NORETURN static void raise(const Type &value, const Type &lbound, const Type &ubound)
|
||||
{
|
||||
throw OutOfBounds((boost::format(
|
||||
"Value is out of bounds ([%1%, %2%] expected, %3% given)") % lbound % ubound % value).str());
|
||||
"value is out of bounds ([%1%, %2%] expected, %3% given)") % lbound % ubound % value).str());
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
GNUC_NORETURN static void raiseLower(const Type &value, const Type &lbound)
|
||||
{
|
||||
throw OutOfBounds((boost::format(
|
||||
"Value is out of bounds ([%1%, ->) expected, %2% given)") % lbound % value).str());
|
||||
"value is out of bounds ([%1%, ->) expected, %2% given)") % lbound % value).str());
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
GNUC_NORETURN static void raiseUpper(const Type &value, const Type &ubound)
|
||||
{
|
||||
throw OutOfBounds((boost::format(
|
||||
"Value is out of bounds ((<-, %1%] expected, %2% given)") % ubound % value).str());
|
||||
"value is out of bounds ((<-, %1%] expected, %2% given)") % ubound % value).str());
|
||||
}
|
||||
|
||||
virtual const char *what() const noexcept OVERRIDE { return m_error_message.c_str(); }
|
||||
|
||||
private:
|
||||
OutOfBounds(std::string msg) : m_error_message(msg) { }
|
||||
|
||||
@@ -115,3 +121,5 @@ void upperBoundCheck(const Type &value, const Type &ubound)
|
||||
if (value > ubound)
|
||||
OutOfBounds::raiseUpper(value, ubound);
|
||||
}
|
||||
|
||||
#endif // NCMPCPP_UTILITY_CONVERSION_H
|
||||
|
||||
37
src/utility/functional.h
Normal file
37
src/utility/functional.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008-2014 by Andrzej Rybczak *
|
||||
* electricityispower@gmail.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef NCMPCPP_UTILITY_FUNCTIONAL_H
|
||||
#define NCMPCPP_UTILITY_FUNCTIONAL_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
// identity function object
|
||||
struct id_
|
||||
{
|
||||
template <typename ValueT>
|
||||
constexpr auto operator()(ValueT &&v) const noexcept
|
||||
-> decltype(std::forward<ValueT>(v))
|
||||
{
|
||||
return std::forward<ValueT>(v);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // NCMPCPP_UTILITY_FUNCTIONAL_H
|
||||
82
src/utility/option_parser.cpp
Normal file
82
src/utility/option_parser.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008-2014 by Andrzej Rybczak *
|
||||
* electricityispower@gmail.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "utility/option_parser.h"
|
||||
|
||||
bool option_parser::run(std::istream &is)
|
||||
{
|
||||
// quoted value. leftmost and rightmost quotation marks are the delimiters.
|
||||
boost::regex quoted("(\\w+)\\h*=\\h*\"(.*)\"[^\"]*");
|
||||
// unquoted value. whitespaces get trimmed.
|
||||
boost::regex unquoted("(\\w+)\\h*=\\h*(.*?)\\h*");
|
||||
boost::smatch match;
|
||||
std::string line;
|
||||
while (std::getline(is, line))
|
||||
{
|
||||
if (boost::regex_match(line, match, quoted)
|
||||
|| boost::regex_match(line, match, unquoted))
|
||||
{
|
||||
std::string option = match[1];
|
||||
auto it = m_parsers.find(option);
|
||||
if (it != m_parsers.end())
|
||||
{
|
||||
try {
|
||||
it->second.parse(match[2]);
|
||||
} catch (std::exception &e) {
|
||||
std::cerr << "Error while processing option \"" << option << "\": " << e.what() << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Unknown option: " << option << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &p : m_parsers)
|
||||
{
|
||||
if (!p.second.defined())
|
||||
{
|
||||
try {
|
||||
p.second.run_default();
|
||||
} catch (std::exception &e) {
|
||||
std::cerr << "Error while finalizing option \"" << p.first << "\": " << e.what() << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
option_parser::worker yes_no(bool &arg, bool value)
|
||||
{
|
||||
return option_parser::worker([&arg](std::string &&v) {
|
||||
if (v == "yes")
|
||||
arg = true;
|
||||
else if (v == "no")
|
||||
arg = false;
|
||||
else
|
||||
throw std::runtime_error("invalid argument: " + v);
|
||||
}, defaults_to(arg, value));
|
||||
}
|
||||
131
src/utility/option_parser.h
Normal file
131
src/utility/option_parser.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008-2014 by Andrzej Rybczak *
|
||||
* electricityispower@gmail.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef NCMPCPP_UTILITY_OPTION_PARSER_H
|
||||
#define NCMPCPP_UTILITY_OPTION_PARSER_H
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "helpers.h"
|
||||
#include "strbuffer.h"
|
||||
#include "utility/functional.h"
|
||||
|
||||
struct option_parser
|
||||
{
|
||||
typedef std::function<void(std::string &&)> parser_t;
|
||||
typedef std::function<void()> default_t;
|
||||
|
||||
struct worker
|
||||
{
|
||||
worker() { }
|
||||
|
||||
template <typename ParserT, typename DefaultT>
|
||||
worker(ParserT &&p, DefaultT &&d)
|
||||
: m_defined(false), m_parser(std::forward<ParserT>(p))
|
||||
, m_default(std::forward<DefaultT>(d)) { }
|
||||
|
||||
template <typename ValueT>
|
||||
void parse(ValueT &&value)
|
||||
{
|
||||
if (m_defined)
|
||||
throw std::runtime_error("option already defined");
|
||||
m_parser(std::forward<ValueT>(value));
|
||||
m_defined = true;
|
||||
}
|
||||
|
||||
bool defined() const { return m_defined; }
|
||||
void run_default() const { m_default(); }
|
||||
|
||||
private:
|
||||
bool m_defined;
|
||||
parser_t m_parser;
|
||||
default_t m_default;
|
||||
};
|
||||
|
||||
template <typename ParserT, typename DefaultT>
|
||||
void add(const std::string &option, ParserT &&p, DefaultT &&d)
|
||||
{
|
||||
assert(m_parsers.count(option) == 0);
|
||||
m_parsers[option] = worker(std::forward<ParserT>(p), std::forward<DefaultT>(d));
|
||||
}
|
||||
|
||||
template <typename WorkerT>
|
||||
void add(const std::string &option, WorkerT &&w)
|
||||
{
|
||||
assert(m_parsers.count(option) == 0);
|
||||
m_parsers[option] = std::forward<WorkerT>(w);
|
||||
}
|
||||
|
||||
bool run(std::istream &is);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, worker> m_parsers;
|
||||
};
|
||||
|
||||
template <typename IntermediateT, typename ArgT, typename TransformT>
|
||||
option_parser::parser_t assign(ArgT &arg, TransformT map = id_())
|
||||
{
|
||||
return [&arg, map](std::string &&v) {
|
||||
try {
|
||||
arg = map(boost::lexical_cast<IntermediateT>(v));
|
||||
} catch (boost::bad_lexical_cast &) {
|
||||
throw std::runtime_error("invalid value: " + v);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename ArgT, typename ValueT>
|
||||
option_parser::default_t defaults_to(ArgT &arg, ValueT &&value)
|
||||
{
|
||||
return [&arg, value] {
|
||||
arg = std::move(value);
|
||||
};
|
||||
}
|
||||
|
||||
template <typename IntermediateT, typename ArgT, typename ValueT, typename TransformT>
|
||||
option_parser::worker assign_default(ArgT &arg, ValueT &&value, TransformT map)
|
||||
{
|
||||
return option_parser::worker(
|
||||
assign<IntermediateT>(arg, map), defaults_to(arg, map(std::forward<ValueT>(value)))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename ArgT, typename ValueT>
|
||||
option_parser::worker assign_default(ArgT &arg, ValueT &&value)
|
||||
{
|
||||
return assign_default<ArgT>(arg, std::forward<ValueT>(value), id_());
|
||||
}
|
||||
|
||||
// workers for specific types
|
||||
|
||||
template <typename ValueT, typename TransformT>
|
||||
option_parser::worker buffer(NC::Buffer &arg, ValueT &&value, TransformT map)
|
||||
{
|
||||
return option_parser::worker(assign<std::string>(arg, [&arg, map](std::string &&s) {
|
||||
return map(stringToBuffer(s));
|
||||
}), defaults_to(arg, map(std::forward<ValueT>(value))));
|
||||
}
|
||||
|
||||
option_parser::worker yes_no(bool &arg, bool value);
|
||||
|
||||
#endif // NCMPCPP_UTILITY_OPTION_PARSER_H
|
||||
Reference in New Issue
Block a user