mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
feat: 💥 update types and retval of parser
- change return value from toml::table to toml::value - enable to change container types and comment policy by template
This commit is contained in:
162
toml/parser.hpp
162
toml/parser.hpp
@@ -869,13 +869,16 @@ parse_key(location<Container>& loc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// forward-decl to implement parse_array and parse_table
|
// forward-decl to implement parse_array and parse_table
|
||||||
template<typename Container>
|
template<typename Value, typename Container>
|
||||||
result<value, std::string> parse_value(location<Container>&);
|
result<Value, std::string> parse_value(location<Container>&);
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Value, typename Container>
|
||||||
result<std::pair<array, region<Container>>, std::string>
|
result<std::pair<typename Value::array_type, region<Container>>, std::string>
|
||||||
parse_array(location<Container>& loc)
|
parse_array(location<Container>& loc)
|
||||||
{
|
{
|
||||||
|
using value_type = Value;
|
||||||
|
using array_type = typename value_type::array_type;
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
if(loc.iter() == loc.end())
|
if(loc.iter() == loc.end())
|
||||||
{
|
{
|
||||||
@@ -890,7 +893,7 @@ parse_array(location<Container>& loc)
|
|||||||
using lex_ws_comment_newline = repeat<
|
using lex_ws_comment_newline = repeat<
|
||||||
either<lex_wschar, lex_newline, lex_comment>, unlimited>;
|
either<lex_wschar, lex_newline, lex_comment>, unlimited>;
|
||||||
|
|
||||||
array retval;
|
array_type retval;
|
||||||
while(loc.iter() != loc.end())
|
while(loc.iter() != loc.end())
|
||||||
{
|
{
|
||||||
lex_ws_comment_newline::invoke(loc); // skip
|
lex_ws_comment_newline::invoke(loc); // skip
|
||||||
@@ -902,7 +905,7 @@ parse_array(location<Container>& loc)
|
|||||||
region<Container>(loc, first, loc.iter())));
|
region<Container>(loc, first, loc.iter())));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto val = parse_value(loc))
|
if(auto val = parse_value<value_type>(loc))
|
||||||
{
|
{
|
||||||
if(!retval.empty() && retval.front().type() != val.as_ok().type())
|
if(!retval.empty() && retval.front().type() != val.as_ok().type())
|
||||||
{
|
{
|
||||||
@@ -966,10 +969,12 @@ parse_array(location<Container>& loc)
|
|||||||
{{std::addressof(loc), "should be closed"}}));
|
{{std::addressof(loc), "should be closed"}}));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Value, typename Container>
|
||||||
result<std::pair<std::pair<std::vector<key>, region<Container>>, value>, std::string>
|
result<std::pair<std::pair<std::vector<key>, region<Container>>, Value>, std::string>
|
||||||
parse_key_value_pair(location<Container>& loc)
|
parse_key_value_pair(location<Container>& loc)
|
||||||
{
|
{
|
||||||
|
using value_type = Value;
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
auto key_reg = parse_key(loc);
|
auto key_reg = parse_key(loc);
|
||||||
if(!key_reg)
|
if(!key_reg)
|
||||||
@@ -1013,7 +1018,7 @@ parse_key_value_pair(location<Container>& loc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto after_kvsp = loc.iter(); // err msg
|
const auto after_kvsp = loc.iter(); // err msg
|
||||||
auto val = parse_value(loc);
|
auto val = parse_value<value_type>(loc);
|
||||||
if(!val)
|
if(!val)
|
||||||
{
|
{
|
||||||
std::string msg;
|
std::string msg;
|
||||||
@@ -1123,9 +1128,9 @@ bool is_valid_forward_table_definition(const value& fwd,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename InputIterator, typename Container>
|
template<typename Value, typename InputIterator, typename Container>
|
||||||
result<bool, std::string>
|
result<bool, std::string>
|
||||||
insert_nested_key(table& root, const toml::value& v,
|
insert_nested_key(typename Value::table_type& root, const Value& v,
|
||||||
InputIterator iter, const InputIterator last,
|
InputIterator iter, const InputIterator last,
|
||||||
region<Container> key_reg,
|
region<Container> key_reg,
|
||||||
const bool is_array_of_table = false)
|
const bool is_array_of_table = false)
|
||||||
@@ -1133,10 +1138,14 @@ insert_nested_key(table& root, const toml::value& v,
|
|||||||
static_assert(std::is_same<key,
|
static_assert(std::is_same<key,
|
||||||
typename std::iterator_traits<InputIterator>::value_type>::value,"");
|
typename std::iterator_traits<InputIterator>::value_type>::value,"");
|
||||||
|
|
||||||
|
using value_type = Value;
|
||||||
|
using table_type = typename value_type::table_type;
|
||||||
|
using array_type = typename value_type::array_type;
|
||||||
|
|
||||||
const auto first = iter;
|
const auto first = iter;
|
||||||
assert(iter != last);
|
assert(iter != last);
|
||||||
|
|
||||||
table* tab = std::addressof(root);
|
table_type* tab = std::addressof(root);
|
||||||
for(; iter != last; ++iter) // search recursively
|
for(; iter != last; ++iter) // search recursively
|
||||||
{
|
{
|
||||||
const key& k = *iter;
|
const key& k = *iter;
|
||||||
@@ -1176,7 +1185,7 @@ insert_nested_key(table& root, const toml::value& v,
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
// the above if-else-if checks tab->at(k) is an array
|
// the above if-else-if checks tab->at(k) is an array
|
||||||
array& a = tab->at(k).as_array();
|
auto& a = tab->at(k).as_array();
|
||||||
if(!(a.front().is_table()))
|
if(!(a.front().is_table()))
|
||||||
{
|
{
|
||||||
throw syntax_error(format_underline(concat_to_string(
|
throw syntax_error(format_underline(concat_to_string(
|
||||||
@@ -1223,7 +1232,7 @@ insert_nested_key(table& root, const toml::value& v,
|
|||||||
}
|
}
|
||||||
else // if not, we need to create the array of table
|
else // if not, we need to create the array of table
|
||||||
{
|
{
|
||||||
toml::value aot(toml::array(1, v), key_reg);
|
value_type aot(array_type(1, v), key_reg);
|
||||||
tab->insert(std::make_pair(k, aot));
|
tab->insert(std::make_pair(k, aot));
|
||||||
return ok(true);
|
return ok(true);
|
||||||
}
|
}
|
||||||
@@ -1298,7 +1307,7 @@ insert_nested_key(table& root, const toml::value& v,
|
|||||||
// [x.y.z]
|
// [x.y.z]
|
||||||
if(tab->count(k) == 0)
|
if(tab->count(k) == 0)
|
||||||
{
|
{
|
||||||
(*tab)[k] = toml::value(toml::table{}, key_reg);
|
(*tab)[k] = value_type(table_type{}, key_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// type checking...
|
// type checking...
|
||||||
@@ -1308,7 +1317,7 @@ insert_nested_key(table& root, const toml::value& v,
|
|||||||
}
|
}
|
||||||
else if(tab->at(k).is_array()) // inserting to array-of-tables?
|
else if(tab->at(k).is_array()) // inserting to array-of-tables?
|
||||||
{
|
{
|
||||||
array& a = (*tab)[k].as_array();
|
auto& a = (*tab)[k].as_array();
|
||||||
if(!a.back().is_table())
|
if(!a.back().is_table())
|
||||||
{
|
{
|
||||||
throw syntax_error(format_underline(concat_to_string(
|
throw syntax_error(format_underline(concat_to_string(
|
||||||
@@ -1338,12 +1347,15 @@ insert_nested_key(table& root, const toml::value& v,
|
|||||||
return err(std::string("toml::detail::insert_nested_key: never reach here"));
|
return err(std::string("toml::detail::insert_nested_key: never reach here"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Value, typename Container>
|
||||||
result<std::pair<table, region<Container>>, std::string>
|
result<std::pair<typename Value::table_type, region<Container>>, std::string>
|
||||||
parse_inline_table(location<Container>& loc)
|
parse_inline_table(location<Container>& loc)
|
||||||
{
|
{
|
||||||
|
using value_type = Value;
|
||||||
|
using table_type = typename value_type::table_type;
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
table retval;
|
table_type retval;
|
||||||
if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
|
if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
|
||||||
{
|
{
|
||||||
return err(format_underline("[error] toml::parse_inline_table: ",
|
return err(format_underline("[error] toml::parse_inline_table: ",
|
||||||
@@ -1361,14 +1373,14 @@ parse_inline_table(location<Container>& loc)
|
|||||||
retval, region<Container>(loc, first, loc.iter())));
|
retval, region<Container>(loc, first, loc.iter())));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto kv_r = parse_key_value_pair(loc);
|
const auto kv_r = parse_key_value_pair<value_type>(loc);
|
||||||
if(!kv_r)
|
if(!kv_r)
|
||||||
{
|
{
|
||||||
return err(kv_r.unwrap_err());
|
return err(kv_r.unwrap_err());
|
||||||
}
|
}
|
||||||
const std::vector<key>& keys = kv_r.unwrap().first.first;
|
const std::vector<key>& keys = kv_r.unwrap().first.first;
|
||||||
const region<Container>& key_reg = kv_r.unwrap().first.second;
|
const region<Container>& key_reg = kv_r.unwrap().first.second;
|
||||||
const value& val = kv_r.unwrap().second;
|
const value_type& val = kv_r.unwrap().second;
|
||||||
|
|
||||||
const auto inserted =
|
const auto inserted =
|
||||||
insert_nested_key(retval, val, keys.begin(), keys.end(), key_reg);
|
insert_nested_key(retval, val, keys.begin(), keys.end(), key_reg);
|
||||||
@@ -1414,22 +1426,22 @@ value_t guess_number_type(const location<Container>& l)
|
|||||||
{
|
{
|
||||||
location<Container> loc = l;
|
location<Container> loc = l;
|
||||||
|
|
||||||
if(lex_offset_date_time::invoke(loc)) {return value_t::OffsetDatetime;}
|
if(lex_offset_date_time::invoke(loc)) {return value_t::offset_datetime;}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
if(lex_local_date_time::invoke(loc)) {return value_t::LocalDatetime;}
|
if(lex_local_date_time::invoke(loc)) {return value_t::local_datetime;}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
if(lex_local_date::invoke(loc)) {return value_t::LocalDate;}
|
if(lex_local_date::invoke(loc)) {return value_t::local_date;}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
if(lex_local_time::invoke(loc)) {return value_t::LocalTime;}
|
if(lex_local_time::invoke(loc)) {return value_t::local_time;}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
if(lex_float::invoke(loc)) {return value_t::Float;}
|
if(lex_float::invoke(loc)) {return value_t::floating;}
|
||||||
loc.reset(l.iter());
|
loc.reset(l.iter());
|
||||||
|
|
||||||
return value_t::Integer;
|
return value_t::integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
@@ -1437,21 +1449,23 @@ value_t guess_value_type(const location<Container>& loc)
|
|||||||
{
|
{
|
||||||
switch(*loc.iter())
|
switch(*loc.iter())
|
||||||
{
|
{
|
||||||
case '"' : {return value_t::String; }
|
case '"' : {return value_t::string; }
|
||||||
case '\'': {return value_t::String; }
|
case '\'': {return value_t::string; }
|
||||||
case 't' : {return value_t::Boolean;}
|
case 't' : {return value_t::boolean; }
|
||||||
case 'f' : {return value_t::Boolean;}
|
case 'f' : {return value_t::boolean; }
|
||||||
case '[' : {return value_t::Array; }
|
case '[' : {return value_t::array; }
|
||||||
case '{' : {return value_t::Table; }
|
case '{' : {return value_t::table; }
|
||||||
case 'i' : {return value_t::Float; } // inf.
|
case 'i' : {return value_t::floating;} // inf.
|
||||||
case 'n' : {return value_t::Float; } // nan.
|
case 'n' : {return value_t::floating;} // nan.
|
||||||
default : {return guess_number_type(loc);}
|
default : {return guess_number_type(loc);}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Value, typename Container>
|
||||||
result<value, std::string> parse_value(location<Container>& loc)
|
result<Value, std::string> parse_value(location<Container>& loc)
|
||||||
{
|
{
|
||||||
|
using value_type = Value;
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
if(first == loc.end())
|
if(first == loc.end())
|
||||||
{
|
{
|
||||||
@@ -1461,16 +1475,16 @@ result<value, std::string> parse_value(location<Container>& loc)
|
|||||||
|
|
||||||
switch(guess_value_type(loc))
|
switch(guess_value_type(loc))
|
||||||
{
|
{
|
||||||
case value_t::Boolean : {return parse_boolean(loc); }
|
case value_t::boolean : {return parse_boolean(loc); }
|
||||||
case value_t::Integer : {return parse_integer(loc); }
|
case value_t::integer : {return parse_integer(loc); }
|
||||||
case value_t::Float : {return parse_floating(loc); }
|
case value_t::floating : {return parse_floating(loc); }
|
||||||
case value_t::String : {return parse_string(loc); }
|
case value_t::string : {return parse_string(loc); }
|
||||||
case value_t::OffsetDatetime : {return parse_offset_datetime(loc);}
|
case value_t::offset_datetime: {return parse_offset_datetime(loc);}
|
||||||
case value_t::LocalDatetime : {return parse_local_datetime(loc); }
|
case value_t::local_datetime : {return parse_local_datetime(loc); }
|
||||||
case value_t::LocalDate : {return parse_local_date(loc); }
|
case value_t::local_date : {return parse_local_date(loc); }
|
||||||
case value_t::LocalTime : {return parse_local_time(loc); }
|
case value_t::local_time : {return parse_local_time(loc); }
|
||||||
case value_t::Array : {return parse_array(loc); }
|
case value_t::array : {return parse_array<value_type>(loc); }
|
||||||
case value_t::Table : {return parse_inline_table(loc); }
|
case value_t::table : {return parse_inline_table<value_type>(loc);}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
const auto msg = format_underline("[error] toml::parse_value: "
|
const auto msg = format_underline("[error] toml::parse_value: "
|
||||||
@@ -1594,13 +1608,17 @@ parse_array_table_key(location<Container>& loc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse table body (key-value pairs until the iter hits the next [tablekey])
|
// parse table body (key-value pairs until the iter hits the next [tablekey])
|
||||||
template<typename Container>
|
template<typename Value, typename Container>
|
||||||
result<table, std::string> parse_ml_table(location<Container>& loc)
|
result<typename Value::table_type, std::string>
|
||||||
|
parse_ml_table(location<Container>& loc)
|
||||||
{
|
{
|
||||||
|
using value_type = Value;
|
||||||
|
using table_type = typename value_type::table_type;
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
if(first == loc.end())
|
if(first == loc.end())
|
||||||
{
|
{
|
||||||
return ok(toml::table{});
|
return ok(table_type{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX at lest one newline is needed.
|
// XXX at lest one newline is needed.
|
||||||
@@ -1608,7 +1626,7 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
|
|||||||
sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>;
|
sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>;
|
||||||
skip_line::invoke(loc);
|
skip_line::invoke(loc);
|
||||||
|
|
||||||
table tab;
|
table_type tab;
|
||||||
while(loc.iter() != loc.end())
|
while(loc.iter() != loc.end())
|
||||||
{
|
{
|
||||||
lex_ws::invoke(loc);
|
lex_ws::invoke(loc);
|
||||||
@@ -1624,11 +1642,11 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
|
|||||||
return ok(tab);
|
return ok(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(const auto kv = parse_key_value_pair(loc))
|
if(const auto kv = parse_key_value_pair<value_type>(loc))
|
||||||
{
|
{
|
||||||
const std::vector<key>& keys = kv.unwrap().first.first;
|
const std::vector<key>& keys = kv.unwrap().first.first;
|
||||||
const region<Container>& key_reg = kv.unwrap().first.second;
|
const region<Container>& key_reg = kv.unwrap().first.second;
|
||||||
const value& val = kv.unwrap().second;
|
const value_type& val = kv.unwrap().second;
|
||||||
const auto inserted =
|
const auto inserted =
|
||||||
insert_nested_key(tab, val, keys.begin(), keys.end(), key_reg);
|
insert_nested_key(tab, val, keys.begin(), keys.end(), key_reg);
|
||||||
if(!inserted)
|
if(!inserted)
|
||||||
@@ -1673,18 +1691,21 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
|
|||||||
return ok(tab);
|
return ok(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container>
|
template<typename Value, typename Container>
|
||||||
result<table, std::string> parse_toml_file(location<Container>& loc)
|
result<Value, std::string> parse_toml_file(location<Container>& loc)
|
||||||
{
|
{
|
||||||
|
using value_type = Value;
|
||||||
|
using table_type = typename value_type::table_type;
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
if(first == loc.end())
|
if(first == loc.end())
|
||||||
{
|
{
|
||||||
return ok(toml::table{});
|
return ok(value_type(table_type{}));
|
||||||
}
|
}
|
||||||
|
|
||||||
table data;
|
table_type data;
|
||||||
// root object is also a table, but without [tablename]
|
// root object is also a table, but without [tablename]
|
||||||
if(auto tab = parse_ml_table(loc))
|
if(auto tab = parse_ml_table<value_type>(loc))
|
||||||
{
|
{
|
||||||
data = std::move(tab.unwrap());
|
data = std::move(tab.unwrap());
|
||||||
}
|
}
|
||||||
@@ -1700,14 +1721,14 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
|
|||||||
// message.
|
// message.
|
||||||
if(const auto tabkey = parse_array_table_key(loc))
|
if(const auto tabkey = parse_array_table_key(loc))
|
||||||
{
|
{
|
||||||
const auto tab = parse_ml_table(loc);
|
const auto tab = parse_ml_table<value_type>(loc);
|
||||||
if(!tab){return err(tab.unwrap_err());}
|
if(!tab){return err(tab.unwrap_err());}
|
||||||
|
|
||||||
const auto& keys = tabkey.unwrap().first;
|
const auto& keys = tabkey.unwrap().first;
|
||||||
const auto& reg = tabkey.unwrap().second;
|
const auto& reg = tabkey.unwrap().second;
|
||||||
|
|
||||||
const auto inserted = insert_nested_key(data,
|
const auto inserted = insert_nested_key(data,
|
||||||
toml::value(tab.unwrap(), reg),
|
value_type(tab.unwrap(), reg),
|
||||||
keys.begin(), keys.end(), reg,
|
keys.begin(), keys.end(), reg,
|
||||||
/*is_array_of_table=*/ true);
|
/*is_array_of_table=*/ true);
|
||||||
if(!inserted) {return err(inserted.unwrap_err());}
|
if(!inserted) {return err(inserted.unwrap_err());}
|
||||||
@@ -1716,14 +1737,14 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
|
|||||||
}
|
}
|
||||||
if(const auto tabkey = parse_table_key(loc))
|
if(const auto tabkey = parse_table_key(loc))
|
||||||
{
|
{
|
||||||
const auto tab = parse_ml_table(loc);
|
const auto tab = parse_ml_table<value_type>(loc);
|
||||||
if(!tab){return err(tab.unwrap_err());}
|
if(!tab){return err(tab.unwrap_err());}
|
||||||
|
|
||||||
const auto& keys = tabkey.unwrap().first;
|
const auto& keys = tabkey.unwrap().first;
|
||||||
const auto& reg = tabkey.unwrap().second;
|
const auto& reg = tabkey.unwrap().second;
|
||||||
|
|
||||||
const auto inserted = insert_nested_key(data,
|
const auto inserted = insert_nested_key(data,
|
||||||
toml::value(tab.unwrap(), reg), keys.begin(), keys.end(), reg);
|
value_type(tab.unwrap(), reg), keys.begin(), keys.end(), reg);
|
||||||
if(!inserted) {return err(inserted.unwrap_err());}
|
if(!inserted) {return err(inserted.unwrap_err());}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -1736,8 +1757,14 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
|
|||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
inline table parse(std::istream& is, std::string fname = "unknown file")
|
template<typename Comment = ::toml::discard_comments,
|
||||||
|
template<typename ...> class Table = std::unordered_map,
|
||||||
|
template<typename ...> class Array = std::vector>
|
||||||
|
basic_value<Comment, Table, Array>
|
||||||
|
parse(std::istream& is, const std::string& fname = "unknown file")
|
||||||
{
|
{
|
||||||
|
using value_type = basic_value<Comment, Table, Array>;
|
||||||
|
|
||||||
const auto beg = is.tellg();
|
const auto beg = is.tellg();
|
||||||
is.seekg(0, std::ios::end);
|
is.seekg(0, std::ios::end);
|
||||||
const auto end = is.tellg();
|
const auto end = is.tellg();
|
||||||
@@ -1767,7 +1794,7 @@ inline table parse(std::istream& is, std::string fname = "unknown file")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto data = detail::parse_toml_file(loc);
|
const auto data = detail::parse_toml_file<value_type>(loc);
|
||||||
if(!data)
|
if(!data)
|
||||||
{
|
{
|
||||||
throw syntax_error(data.unwrap_err());
|
throw syntax_error(data.unwrap_err());
|
||||||
@@ -1775,14 +1802,17 @@ inline table parse(std::istream& is, std::string fname = "unknown file")
|
|||||||
return data.unwrap();
|
return data.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline table parse(const std::string& fname)
|
template<typename Comment = ::toml::discard_comments,
|
||||||
|
template<typename ...> class Table = std::unordered_map,
|
||||||
|
template<typename ...> class Array = std::vector>
|
||||||
|
inline basic_value<Comment, Table, Array> parse(const std::string& fname)
|
||||||
{
|
{
|
||||||
std::ifstream ifs(fname.c_str(), std::ios_base::binary);
|
std::ifstream ifs(fname.c_str(), std::ios_base::binary);
|
||||||
if(!ifs.good())
|
if(!ifs.good())
|
||||||
{
|
{
|
||||||
throw std::runtime_error("toml::parse: file open error -> " + fname);
|
throw std::runtime_error("toml::parse: file open error -> " + fname);
|
||||||
}
|
}
|
||||||
return parse(ifs, fname);
|
return parse<Comment, Table, Array>(ifs, fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // toml
|
} // toml
|
||||||
|
|||||||
Reference in New Issue
Block a user