Refactor option_from_string to return directly the option value
This commit is contained in:
parent
2617f5e022
commit
b5693c6253
|
@ -81,9 +81,9 @@ String option_to_string(Color color)
|
||||||
return to_string(color);
|
return to_string(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void option_from_string(StringView str, Color& color)
|
Color option_from_string(Meta::Type<Color>, StringView str)
|
||||||
{
|
{
|
||||||
color = str_to_color(str);
|
return str_to_color(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define color_hh_INCLUDED
|
#define color_hh_INCLUDED
|
||||||
|
|
||||||
#include "hash.hh"
|
#include "hash.hh"
|
||||||
|
#include "meta.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -59,7 +60,7 @@ Color str_to_color(StringView color);
|
||||||
String to_string(Color color);
|
String to_string(Color color);
|
||||||
|
|
||||||
String option_to_string(Color color);
|
String option_to_string(Color color);
|
||||||
void option_from_string(StringView str, Color& color);
|
Color option_from_string(Meta::Type<Color>, StringView str);
|
||||||
|
|
||||||
bool is_color_name(StringView color);
|
bool is_color_name(StringView color);
|
||||||
|
|
||||||
|
|
|
@ -1379,7 +1379,7 @@ String option_to_string(InclusiveBufferRange range)
|
||||||
range.last.line+1, range.last.column+1);
|
range.last.line+1, range.last.column+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void option_from_string(StringView str, InclusiveBufferRange& opt)
|
InclusiveBufferRange option_from_string(Meta::Type<InclusiveBufferRange>, StringView str)
|
||||||
{
|
{
|
||||||
auto sep = find_if(str, [](char c){ return c == ',' or c == '+'; });
|
auto sep = find_if(str, [](char c){ return c == ',' or c == '+'; });
|
||||||
auto dot_beg = find(StringView{str.begin(), sep}, '.');
|
auto dot_beg = find(StringView{str.begin(), sep}, '.');
|
||||||
|
@ -1400,7 +1400,7 @@ void option_from_string(StringView str, InclusiveBufferRange& opt)
|
||||||
if (first.line < 0 or first.column < 0 or last.line < 0 or last.column < 0)
|
if (first.line < 0 or first.column < 0 or last.line < 0 or last.column < 0)
|
||||||
throw runtime_error("coordinates elements should be >= 1");
|
throw runtime_error("coordinates elements should be >= 1");
|
||||||
|
|
||||||
opt = { std::min(first, last), std::max(first, last) };
|
return { std::min(first, last), std::max(first, last) };
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferCoord& get_first(RangeAndString& r) { return std::get<0>(r).first; }
|
BufferCoord& get_first(RangeAndString& r) { return std::get<0>(r).first; }
|
||||||
|
|
|
@ -17,7 +17,7 @@ inline bool operator==(const InclusiveBufferRange& lhs, const InclusiveBufferRan
|
||||||
return lhs.first == rhs.first and lhs.last == rhs.last;
|
return lhs.first == rhs.first and lhs.last == rhs.last;
|
||||||
}
|
}
|
||||||
String option_to_string(InclusiveBufferRange range);
|
String option_to_string(InclusiveBufferRange range);
|
||||||
void option_from_string(StringView str, InclusiveBufferRange& opt);
|
InclusiveBufferRange option_from_string(Meta::Type<InclusiveBufferRange>, StringView str);
|
||||||
|
|
||||||
using LineAndSpec = std::tuple<LineCount, String>;
|
using LineAndSpec = std::tuple<LineCount, String>;
|
||||||
using LineAndSpecList = TimestampedList<LineAndSpec>;
|
using LineAndSpecList = TimestampedList<LineAndSpec>;
|
||||||
|
|
|
@ -40,39 +40,23 @@ String option_to_string(const InsertCompleterDesc& opt)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void option_from_string(StringView str, InsertCompleterDesc& opt)
|
InsertCompleterDesc option_from_string(Meta::Type<InsertCompleterDesc>, StringView str)
|
||||||
{
|
{
|
||||||
if (str.substr(0_byte, 7_byte) == "option=")
|
if (str.substr(0_byte, 7_byte) == "option=")
|
||||||
{
|
return {InsertCompleterDesc::Option, str.substr(7_byte).str()};
|
||||||
opt.mode = InsertCompleterDesc::Option;
|
|
||||||
opt.param = str.substr(7_byte).str();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (str.substr(0_byte, 5_byte) == "word=")
|
else if (str.substr(0_byte, 5_byte) == "word=")
|
||||||
{
|
{
|
||||||
auto param = str.substr(5_byte);
|
auto param = str.substr(5_byte);
|
||||||
if (param == "all" or param == "buffer")
|
if (param == "all" or param == "buffer")
|
||||||
{
|
return {InsertCompleterDesc::Word, param.str()};
|
||||||
opt.mode = InsertCompleterDesc::Word;
|
|
||||||
opt.param = param.str();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (str == "filename")
|
else if (str == "filename")
|
||||||
{
|
return {InsertCompleterDesc::Filename, {}};
|
||||||
opt.mode = InsertCompleterDesc::Filename;
|
|
||||||
opt.param = Optional<String>{};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (str.substr(0_byte, 5_byte) == "line=")
|
else if (str.substr(0_byte, 5_byte) == "line=")
|
||||||
{
|
{
|
||||||
auto param = str.substr(5_byte);
|
auto param = str.substr(5_byte);
|
||||||
if (param == "all" or param == "buffer")
|
if (param == "all" or param == "buffer")
|
||||||
{
|
return {InsertCompleterDesc::Line, param.str()};
|
||||||
opt.mode = InsertCompleterDesc::Line;
|
|
||||||
opt.param = param.str();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
throw runtime_error(format("invalid completer description: '{}'", str));
|
throw runtime_error(format("invalid completer description: '{}'", str));
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ struct InsertCompleterDesc
|
||||||
using InsertCompleterDescList = Vector<InsertCompleterDesc, MemoryDomain::Options>;
|
using InsertCompleterDescList = Vector<InsertCompleterDesc, MemoryDomain::Options>;
|
||||||
|
|
||||||
String option_to_string(const InsertCompleterDesc& opt);
|
String option_to_string(const InsertCompleterDesc& opt);
|
||||||
void option_from_string(StringView str, InsertCompleterDesc& opt);
|
InsertCompleterDesc option_from_string(Meta::Type<InsertCompleterDesc>, StringView str);
|
||||||
|
|
||||||
inline StringView option_type_name(Meta::Type<InsertCompleterDesc>)
|
inline StringView option_type_name(Meta::Type<InsertCompleterDesc>)
|
||||||
{
|
{
|
||||||
|
|
|
@ -147,9 +147,7 @@ public:
|
||||||
}
|
}
|
||||||
void set_from_string(StringView str) override
|
void set_from_string(StringView str) override
|
||||||
{
|
{
|
||||||
T val;
|
set(option_from_string(Meta::Type<T>{}, str));
|
||||||
option_from_string(str, val);
|
|
||||||
set(std::move(val));
|
|
||||||
}
|
}
|
||||||
void add_from_string(StringView str) override
|
void add_from_string(StringView str) override
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,8 +9,7 @@ UnitTest test_option_parsing{[]{
|
||||||
{
|
{
|
||||||
auto repr = option_to_string(value);
|
auto repr = option_to_string(value);
|
||||||
kak_assert(repr == str);
|
kak_assert(repr == str);
|
||||||
std::decay_t<decltype(value)> parsed;
|
auto parsed = option_from_string(Meta::Type<std::decay_t<decltype(value)>>{}, str);
|
||||||
option_from_string(str, parsed);
|
|
||||||
kak_assert(parsed == value);
|
kak_assert(parsed == value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ option_type_name(Meta::Type<Enum>)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String option_to_string(int opt) { return to_string(opt); }
|
inline String option_to_string(int opt) { return to_string(opt); }
|
||||||
inline void option_from_string(StringView str, int& opt) { opt = str_to_int(str); }
|
inline int option_from_string(Meta::Type<int>, StringView str) { return str_to_int(str); }
|
||||||
inline bool option_add(int& opt, StringView str)
|
inline bool option_add(int& opt, StringView str)
|
||||||
{
|
{
|
||||||
auto val = str_to_int(str);
|
auto val = str_to_int(str);
|
||||||
|
@ -44,26 +44,26 @@ inline bool option_add(int& opt, StringView str)
|
||||||
constexpr StringView option_type_name(Meta::Type<int>) { return "int"; }
|
constexpr StringView option_type_name(Meta::Type<int>) { return "int"; }
|
||||||
|
|
||||||
inline String option_to_string(size_t opt) { return to_string(opt); }
|
inline String option_to_string(size_t opt) { return to_string(opt); }
|
||||||
inline void option_from_string(StringView str, size_t& opt) { opt = str_to_int(str); }
|
inline size_t option_from_string(Meta::Type<size_t>, StringView str) { return str_to_int(str); }
|
||||||
|
|
||||||
inline String option_to_string(bool opt) { return opt ? "true" : "false"; }
|
inline String option_to_string(bool opt) { return opt ? "true" : "false"; }
|
||||||
inline void option_from_string(StringView str, bool& opt)
|
inline bool option_from_string(Meta::Type<bool>, StringView str)
|
||||||
{
|
{
|
||||||
if (str == "true" or str == "yes")
|
if (str == "true" or str == "yes")
|
||||||
opt = true;
|
return true;
|
||||||
else if (str == "false" or str == "no")
|
else if (str == "false" or str == "no")
|
||||||
opt = false;
|
return false;
|
||||||
else
|
else
|
||||||
throw runtime_error("boolean values are either true, yes, false or no");
|
throw runtime_error("boolean values are either true, yes, false or no");
|
||||||
}
|
}
|
||||||
constexpr StringView option_type_name(Meta::Type<bool>) { return "bool"; }
|
constexpr StringView option_type_name(Meta::Type<bool>) { return "bool"; }
|
||||||
|
|
||||||
inline String option_to_string(Codepoint opt) { return to_string(opt); }
|
inline String option_to_string(Codepoint opt) { return to_string(opt); }
|
||||||
inline void option_from_string(StringView str, Codepoint& opt)
|
inline Codepoint option_from_string(Meta::Type<Codepoint>, StringView str)
|
||||||
{
|
{
|
||||||
if (str.char_length() != 1)
|
if (str.char_length() != 1)
|
||||||
throw runtime_error{format("'{}' is not a single codepoint", str)};
|
throw runtime_error{format("'{}' is not a single codepoint", str)};
|
||||||
opt = str[0_char];
|
return str[0_char];
|
||||||
}
|
}
|
||||||
constexpr StringView option_type_name(Meta::Type<Codepoint>) { return "codepoint"; }
|
constexpr StringView option_type_name(Meta::Type<Codepoint>) { return "codepoint"; }
|
||||||
|
|
||||||
|
@ -81,24 +81,20 @@ void option_list_postprocess(Vector<T, domain>& opt)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename T, MemoryDomain domain>
|
template<typename T, MemoryDomain domain>
|
||||||
void option_from_string(StringView str, Vector<T, domain>& opt)
|
Vector<T, domain> option_from_string(Meta::Type<Vector<T, domain>>, StringView str)
|
||||||
{
|
{
|
||||||
opt.clear();
|
auto res = str | split<StringView>(list_separator, '\\')
|
||||||
for (auto&& elem : str | split<StringView>(list_separator, '\\')
|
| transform(unescape<list_separator, '\\'>)
|
||||||
| transform(unescape<list_separator, '\\'>))
|
| transform([](auto&& s) { return option_from_string(Meta::Type<T>{}, s); })
|
||||||
{
|
| gather<Vector<T, domain>>();
|
||||||
T opt_elem;
|
option_list_postprocess(res);
|
||||||
option_from_string(elem, opt_elem);
|
return res;
|
||||||
opt.push_back(opt_elem);
|
|
||||||
}
|
|
||||||
option_list_postprocess(opt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, MemoryDomain domain>
|
template<typename T, MemoryDomain domain>
|
||||||
bool option_add(Vector<T, domain>& opt, StringView str)
|
bool option_add(Vector<T, domain>& opt, StringView str)
|
||||||
{
|
{
|
||||||
Vector<T, domain> vec;
|
auto vec = option_from_string(Meta::Type<Vector<T, domain>>{}, str);
|
||||||
option_from_string(str, vec);
|
|
||||||
opt.insert(opt.end(),
|
opt.insert(opt.end(),
|
||||||
std::make_move_iterator(vec.begin()),
|
std::make_move_iterator(vec.begin()),
|
||||||
std::make_move_iterator(vec.end()));
|
std::make_move_iterator(vec.end()));
|
||||||
|
@ -139,20 +135,18 @@ bool option_add(HashMap<Key, Value, domain>& opt, StringView str)
|
||||||
| transform(unescape<'=', '\\'>)
|
| transform(unescape<'=', '\\'>)
|
||||||
| static_gather<error, 2>();
|
| static_gather<error, 2>();
|
||||||
|
|
||||||
HashItem<Key, Value> item;
|
opt[option_from_string(Meta::Type<Key>{}, key_value[0])] = option_from_string(Meta::Type<Value>{}, key_value[1]);
|
||||||
option_from_string(key_value[0], item.key);
|
|
||||||
option_from_string(key_value[1], item.value);
|
|
||||||
opt[std::move(item.key)] = std::move(item.value);
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Key, typename Value, MemoryDomain domain>
|
template<typename Key, typename Value, MemoryDomain domain>
|
||||||
void option_from_string(StringView str, HashMap<Key, Value, domain>& opt)
|
HashMap<Key, Value, domain> option_from_string(Meta::Type<HashMap<Key, Value, domain>>, StringView str)
|
||||||
{
|
{
|
||||||
opt.clear();
|
HashMap<Key, Value, domain> res;
|
||||||
option_add(opt, str);
|
option_add(res, str);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename K, typename V, MemoryDomain D>
|
template<typename K, typename V, MemoryDomain D>
|
||||||
|
@ -164,44 +158,21 @@ String option_type_name(Meta::Type<HashMap<K, V, D>>)
|
||||||
|
|
||||||
constexpr char tuple_separator = '|';
|
constexpr char tuple_separator = '|';
|
||||||
|
|
||||||
template<size_t I, typename... Types>
|
template<typename... Types, size_t... I>
|
||||||
struct TupleOptionDetail
|
String option_to_string_impl(const std::tuple<Types...>& opt, std::index_sequence<I...>)
|
||||||
{
|
{
|
||||||
static String to_string(const std::tuple<Types...>& opt)
|
return join(make_array({option_to_string(std::get<I>(opt))...}), tuple_separator);
|
||||||
{
|
}
|
||||||
return TupleOptionDetail<I-1, Types...>::to_string(opt) +
|
|
||||||
tuple_separator + escape(option_to_string(std::get<I>(opt)), tuple_separator, '\\');
|
|
||||||
}
|
|
||||||
|
|
||||||
static void from_string(ConstArrayView<String> elems, std::tuple<Types...>& opt)
|
|
||||||
{
|
|
||||||
option_from_string(elems[I], std::get<I>(opt));
|
|
||||||
TupleOptionDetail<I-1, Types...>::from_string(elems, opt);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Types>
|
|
||||||
struct TupleOptionDetail<0, Types...>
|
|
||||||
{
|
|
||||||
static String to_string(const std::tuple<Types...>& opt)
|
|
||||||
{
|
|
||||||
return option_to_string(std::get<0>(opt));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void from_string(ConstArrayView<String> elems, std::tuple<Types...>& opt)
|
|
||||||
{
|
|
||||||
option_from_string(elems[0], std::get<0>(opt));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Types>
|
template<typename... Types>
|
||||||
String option_to_string(const std::tuple<Types...>& opt)
|
String option_to_string(const std::tuple<Types...>& opt)
|
||||||
{
|
{
|
||||||
return TupleOptionDetail<sizeof...(Types)-1, Types...>::to_string(opt);
|
return option_to_string_impl(opt, std::make_index_sequence<sizeof...(Types)>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Types>
|
template<typename... Types, size_t... I>
|
||||||
void option_from_string(StringView str, std::tuple<Types...>& opt)
|
std::tuple<Types...> option_from_string_impl(Meta::Type<std::tuple<Types...>>, StringView str,
|
||||||
|
std::index_sequence<I...>)
|
||||||
{
|
{
|
||||||
struct error : runtime_error
|
struct error : runtime_error
|
||||||
{
|
{
|
||||||
|
@ -212,8 +183,14 @@ void option_from_string(StringView str, std::tuple<Types...>& opt)
|
||||||
auto elems = str | split<StringView>(tuple_separator, '\\')
|
auto elems = str | split<StringView>(tuple_separator, '\\')
|
||||||
| transform(unescape<tuple_separator, '\\'>)
|
| transform(unescape<tuple_separator, '\\'>)
|
||||||
| static_gather<error, sizeof...(Types)>();
|
| static_gather<error, sizeof...(Types)>();
|
||||||
|
return {option_from_string(Meta::Type<Types>{}, elems[I])...};
|
||||||
|
}
|
||||||
|
|
||||||
TupleOptionDetail<sizeof...(Types)-1, Types...>::from_string(elems, opt);
|
template<typename... Types>
|
||||||
|
std::tuple<Types...> option_from_string(Meta::Type<std::tuple<Types...>>, StringView str)
|
||||||
|
{
|
||||||
|
return option_from_string_impl(Meta::Type<std::tuple<Types...>>{}, str,
|
||||||
|
std::make_index_sequence<sizeof...(Types)>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RealType, typename ValueType>
|
template<typename RealType, typename ValueType>
|
||||||
|
@ -222,15 +199,15 @@ inline String option_to_string(const StronglyTypedNumber<RealType, ValueType>& o
|
||||||
return to_string(opt);
|
return to_string(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RealType, typename ValueType>
|
template<typename Number>
|
||||||
inline void option_from_string(StringView str, StronglyTypedNumber<RealType, ValueType>& opt)
|
std::enable_if_t<std::is_base_of<StronglyTypedNumber<Number, int>, Number>::value, Number>
|
||||||
|
option_from_string(Meta::Type<Number>, StringView str)
|
||||||
{
|
{
|
||||||
opt = StronglyTypedNumber<RealType, ValueType>{str_to_int(str)};
|
return Number{str_to_int(str)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RealType, typename ValueType>
|
template<typename RealType, typename ValueType>
|
||||||
inline bool option_add(StronglyTypedNumber<RealType, ValueType>& opt,
|
inline bool option_add(StronglyTypedNumber<RealType, ValueType>& opt, StringView str)
|
||||||
StringView str)
|
|
||||||
{
|
{
|
||||||
int val = str_to_int(str);
|
int val = str_to_int(str);
|
||||||
opt += val;
|
opt += val;
|
||||||
|
@ -251,14 +228,14 @@ inline void option_update(WorstMatch, const Context&)
|
||||||
throw runtime_error("no update operation supported for this option type");
|
throw runtime_error("no update operation supported for this option type");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename EffectiveType, typename LineType, typename ColumnType>
|
template<typename Coord>
|
||||||
inline void option_from_string(StringView str, LineAndColumn<EffectiveType, LineType, ColumnType>& opt)
|
std::enable_if_t<std::is_base_of<LineAndColumn<Coord, decltype(Coord::line), decltype(Coord::column)>, Coord>::value, Coord>
|
||||||
|
option_from_string(Meta::Type<Coord>, StringView str)
|
||||||
{
|
{
|
||||||
struct error : runtime_error { error(size_t) : runtime_error{"expected <line>,<column>"} {} };
|
struct error : runtime_error { error(size_t) : runtime_error{"expected <line>,<column>"} {} };
|
||||||
auto vals = str | split<StringView>(',')
|
auto vals = str | split<StringView>(',')
|
||||||
| static_gather<error, 2>();
|
| static_gather<error, 2>();
|
||||||
opt.line = str_to_int(vals[0]);
|
return {str_to_int(vals[0]), str_to_int(vals[1])};
|
||||||
opt.column = str_to_int(vals[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename EffectiveType, typename LineType, typename ColumnType>
|
template<typename EffectiveType, typename LineType, typename ColumnType>
|
||||||
|
@ -295,10 +272,10 @@ EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
||||||
EnableIfWithBitOps<Flags> option_from_string(StringView str, Flags& flags)
|
EnableIfWithBitOps<Flags, Flags> option_from_string(Meta::Type<Flags>, StringView str)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
||||||
flags = Flags{};
|
Flags flags{};
|
||||||
for (auto s : str | split<StringView>('|'))
|
for (auto s : str | split<StringView>('|'))
|
||||||
{
|
{
|
||||||
auto it = find_if(desc, [s](const EnumDesc<Flags>& d) { return d.name == s; });
|
auto it = find_if(desc, [s](const EnumDesc<Flags>& d) { return d.name == s; });
|
||||||
|
@ -306,23 +283,23 @@ EnableIfWithBitOps<Flags> option_from_string(StringView str, Flags& flags)
|
||||||
throw runtime_error(format("invalid flag value '{}'", s));
|
throw runtime_error(format("invalid flag value '{}'", s));
|
||||||
flags |= it->value;
|
flags |= it->value;
|
||||||
}
|
}
|
||||||
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))>
|
template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))>
|
||||||
EnableIfWithoutBitOps<Enum> option_from_string(StringView str, Enum& e)
|
EnableIfWithoutBitOps<Enum, Enum> option_from_string(Meta::Type<Enum>, StringView str)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Meta::Type<Enum>{});
|
constexpr auto desc = enum_desc(Meta::Type<Enum>{});
|
||||||
auto it = find_if(desc, [str](const EnumDesc<Enum>& d) { return d.name == str; });
|
auto it = find_if(desc, [str](const EnumDesc<Enum>& d) { return d.name == str; });
|
||||||
if (it == desc.end())
|
if (it == desc.end())
|
||||||
throw runtime_error(format("invalid enum value '{}'", str));
|
throw runtime_error(format("invalid enum value '{}'", str));
|
||||||
e = it->value;
|
return it->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
||||||
EnableIfWithBitOps<Flags, bool> option_add(Flags& opt, StringView str)
|
EnableIfWithBitOps<Flags, bool> option_add(Flags& opt, StringView str)
|
||||||
{
|
{
|
||||||
Flags res = Flags{};
|
const Flags res = option_from_string(Meta::Type<Flags>{}, str);
|
||||||
option_from_string(str, res);
|
|
||||||
opt |= res;
|
opt |= res;
|
||||||
return res != (Flags)0;
|
return res != (Flags)0;
|
||||||
}
|
}
|
||||||
|
@ -338,12 +315,12 @@ inline String option_to_string(const PrefixedList<P, T>& opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename P, typename T>
|
template<typename P, typename T>
|
||||||
inline void option_from_string(StringView str, PrefixedList<P, T>& opt)
|
inline PrefixedList<P, T> option_from_string(Meta::Type<PrefixedList<P, T>>, StringView str)
|
||||||
{
|
{
|
||||||
|
using VecType = Vector<T, MemoryDomain::Options>;
|
||||||
auto it = find(str, list_separator);
|
auto it = find(str, list_separator);
|
||||||
option_from_string(StringView{str.begin(), it}, opt.prefix);
|
return {option_from_string(Meta::Type<P>{}, StringView{str.begin(), it}),
|
||||||
if (it != str.end())
|
it != str.end() ? option_from_string(Meta::Type<VecType>{}, {it+1, str.end()}) : VecType{}};
|
||||||
option_from_string({it+1, str.end()}, opt.list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename P, typename T>
|
template<typename P, typename T>
|
||||||
|
|
|
@ -13,9 +13,9 @@ String option_to_string(const Regex& re)
|
||||||
return re.str();
|
return re.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void option_from_string(StringView str, Regex& re)
|
Regex option_from_string(Meta::Type<Regex>, StringView str)
|
||||||
{
|
{
|
||||||
re = Regex{str};
|
return Regex{str};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,7 @@ bool backward_regex_search(It begin, It end, It subject_begin, It subject_end,
|
||||||
}
|
}
|
||||||
|
|
||||||
String option_to_string(const Regex& re);
|
String option_to_string(const Regex& re);
|
||||||
void option_from_string(StringView str, Regex& re);
|
Regex option_from_string(Meta::Type<Regex>, StringView str);
|
||||||
|
|
||||||
template<typename Iterator, MatchDirection direction = MatchDirection::Forward>
|
template<typename Iterator, MatchDirection direction = MatchDirection::Forward>
|
||||||
struct RegexIterator
|
struct RegexIterator
|
||||||
|
|
|
@ -66,7 +66,7 @@ int str_to_int(StringView str); // throws on error
|
||||||
Optional<int> str_to_int_ifp(StringView str);
|
Optional<int> str_to_int_ifp(StringView str);
|
||||||
|
|
||||||
inline String option_to_string(StringView opt) { return opt.str(); }
|
inline String option_to_string(StringView opt) { return opt.str(); }
|
||||||
inline void option_from_string(StringView str, String& opt) { opt = str.str(); }
|
inline String option_from_string(Meta::Type<String>, StringView str) { return str.str(); }
|
||||||
inline bool option_add(String& opt, StringView val) { opt += val; return not val.empty(); }
|
inline bool option_add(String& opt, StringView val) { opt += val; return not val.empty(); }
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user