25 #include <unordered_map> 28 #if __cplusplus > 201103L 29 #define CPPTOML_DEPRECATED(reason) [[deprecated(reason)]] 30 #elif defined(__clang__) 31 #define CPPTOML_DEPRECATED(reason) __attribute__((deprecated(reason))) 32 #elif defined(__GNUG__) 33 #define CPPTOML_DEPRECATED(reason) __attribute__((deprecated)) 34 #elif defined(_MSC_VER) 36 #define CPPTOML_DEPRECATED(reason) __declspec(deprecated) 38 #define CPPTOML_DEPRECATED(reason) [[deprecated(reason)]] 46 #if defined(CPPTOML_USE_MAP) 54 = std::unordered_map<std::string, std::shared_ptr<base>>;
75 explicit operator bool()
const 95 return static_cast<T
>(std::forward<U>(alternative));
121 int minute_offset = 0;
133 dt.
year = t.tm_year + 1900;
134 dt.
month = t.tm_mon + 1;
141 strftime(buf, 16,
"%z", &t);
143 int offset = std::stoi(buf);
149 CPPTOML_DEPRECATED(
"from_local has been renamed to from_zoned")
152 return from_zoned(t);
158 dt.
year = t.tm_year + 1900;
159 dt.
month = t.tm_mon + 1;
168 CPPTOML_DEPRECATED(
"datetime has been renamed to offset_datetime")
195 os << setw(4) << dt.
year <<
"-" << setw(2) << dt.
month <<
"-" << setw(2)
207 os << setw(2) << ltime.
hour <<
":" << setw(2) << ltime.
minute <<
":" 208 << setw(2) << ltime.
second;
214 for (
int curr_us = ltime.
microsecond; curr_us; power /= 10)
216 auto num = curr_us / power;
218 curr_us -= num * power;
242 os << setw(2) << std::abs(zo.
hour_offset) <<
":" << setw(2)
255 return os << static_cast<const local_date&>(dt) <<
"T" 256 << static_cast<const local_time&>(dt);
261 return os << static_cast<const local_datetime&>(dt)
262 << static_cast<const zone_offset&>(dt);
265 template <
class T,
class... Ts>
268 template <
class T,
class V>
273 template <
class T,
class V,
class... Ts>
276 const static bool value 285 :
is_one_of<T, std::string, int64_t, double, bool, local_date, local_time,
286 local_datetime, offset_datetime>
290 template <
class T,
class Enable =
void>
298 || std::is_convertible<T, std::string>::value;
303 valid_value_or_string_convertible<T>::value>
::type>
307 typename std::decay<T>::type, std::string>
::type;
313 return value_type(val);
320 typename
std::enable_if<
321 !valid_value_or_string_convertible<T>::value
322 && std::is_floating_point<typename std::decay<T>::type>::value>
::type>
336 T, typename
std::enable_if<
337 !valid_value_or_string_convertible<T>::value
338 && !std::is_floating_point<typename std::decay<T>::type>::value
339 && std::is_signed<typename std::decay<T>::type>::value>
::type>
347 if (val < (std::numeric_limits<int64_t>::min)())
348 throw std::underflow_error{
"constructed value cannot be " 349 "represented by a 64-bit signed " 352 if (val > (std::numeric_limits<int64_t>::max)())
353 throw std::overflow_error{
"constructed value cannot be represented " 354 "by a 64-bit signed integer"};
356 return static_cast<int64_t
>(val);
362 T, typename
std::enable_if<
363 !valid_value_or_string_convertible<T>::value
364 && std::is_unsigned<typename std::decay<T>::type>::value>
::type>
372 if (val > static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
373 throw std::overflow_error{
"constructed value cannot be represented " 374 "by a 64-bit signed integer"};
376 return static_cast<int64_t
>(val);
397 inline std::shared_ptr<typename value_traits<T>::type>
make_value(T&& val);
407 inline std::shared_ptr<table_array>
make_table_array(
bool is_inline =
false);
409 #if defined(CPPTOML_NO_RTTI) 429 struct base_type_traits;
432 struct base_type_traits<
std::string>
434 static const base_type type = base_type::STRING;
438 struct base_type_traits<local_time>
440 static const base_type type = base_type::LOCAL_TIME;
444 struct base_type_traits<local_date>
446 static const base_type type = base_type::LOCAL_DATE;
450 struct base_type_traits<local_datetime>
452 static const base_type type = base_type::LOCAL_DATETIME;
456 struct base_type_traits<offset_datetime>
458 static const base_type type = base_type::OFFSET_DATETIME;
462 struct base_type_traits<int64_t>
464 static const base_type type = base_type::INT;
468 struct base_type_traits<double>
470 static const base_type type = base_type::FLOAT;
474 struct base_type_traits<bool>
476 static const base_type type = base_type::BOOL;
480 struct base_type_traits<table>
482 static const base_type type = base_type::TABLE;
486 struct base_type_traits<array>
488 static const base_type type = base_type::ARRAY;
492 struct base_type_traits<table_array>
494 static const base_type type = base_type::TABLE_ARRAY;
501 class base :
public std::enable_shared_from_this<base>
504 virtual ~
base() =
default;
506 virtual std::shared_ptr<base> clone()
const = 0;
530 return std::static_pointer_cast<table>(shared_from_this());
547 return std::static_pointer_cast<array>(shared_from_this());
564 if (is_table_array())
565 return std::static_pointer_cast<table_array>(shared_from_this());
574 std::shared_ptr<value<T>> as();
577 std::shared_ptr<const value<T>> as()
const;
579 template <
class Visitor,
class... Args>
580 void accept(Visitor&& visitor, Args&&... args)
const;
582 #if defined(CPPTOML_NO_RTTI) 583 base_type type()
const 589 base(
const base_type t) : type_(t)
595 const base_type type_ = base_type::NONE;
618 friend std::shared_ptr<typename value_traits<U>::type>
624 std::shared_ptr<base> clone()
const override;
659 #if defined(CPPTOML_NO_RTTI) 660 value(
const T& val) :
base(base_type_traits<T>::type), data_(val)
674 std::shared_ptr<typename value_traits<T>::type>
make_value(T&& val)
677 using enabler =
typename value_type::make_shared_enabler;
678 return std::make_shared<value_type>(
685 #if defined(CPPTOML_NO_RTTI) 686 if (type() == base_type_traits<T>::type)
687 return std::static_pointer_cast<
value<T>>(shared_from_this());
691 return std::dynamic_pointer_cast<value<T>>(shared_from_this());
700 #if defined(CPPTOML_NO_RTTI) 701 if (type() == base_type::FLOAT)
702 return std::static_pointer_cast<
value<double>>(shared_from_this());
704 if (type() == base_type::INT)
706 auto v = std::static_pointer_cast<
value<int64_t>>(shared_from_this());
707 return make_value<double>(
static_cast<double>(v->get()));
710 if (
auto v = std::dynamic_pointer_cast<
value<double>>(shared_from_this()))
713 if (
auto v = std::dynamic_pointer_cast<
value<int64_t>>(shared_from_this()))
714 return make_value<double>(
static_cast<double>(v->get()));
721 inline std::shared_ptr<const value<T>>
base::as()
const 723 #if defined(CPPTOML_NO_RTTI) 724 if (type() == base_type_traits<T>::type)
725 return std::static_pointer_cast<
const value<T>>(shared_from_this());
729 return std::dynamic_pointer_cast<
const value<T>>(shared_from_this());
736 inline std::shared_ptr<const value<double>>
base::as()
const 738 #if defined(CPPTOML_NO_RTTI) 739 if (type() == base_type::FLOAT)
743 if (type() == base_type::INT)
745 auto v = as<int64_t>();
748 return make_value<double>(
static_cast<double>(v->get()));
752 = std::dynamic_pointer_cast<
const value<double>>(shared_from_this()))
755 if (
auto v = as<int64_t>())
759 return make_value<double>(
static_cast<double>(v->get()));
782 std::shared_ptr<base> clone()
const override;
803 return values_.begin();
808 return values_.begin();
813 return values_.end();
818 return values_.end();
824 std::vector<std::shared_ptr<base>>&
get()
832 const std::vector<std::shared_ptr<base>>&
get()
const 837 std::shared_ptr<base>
at(
size_t idx)
const 839 return values_.at(idx);
847 std::vector<std::shared_ptr<value<T>>>
array_of()
const 849 std::vector<std::shared_ptr<value<T>>> result(values_.size());
851 std::transform(values_.begin(), values_.end(), result.begin(),
852 [&](std::shared_ptr<base> v) {
return v->as<T>(); });
864 std::vector<T> result;
865 result.reserve(values_.size());
867 for (
const auto& val : values_)
869 if (
auto v = val->as<T>())
870 result.push_back(v->get());
875 return {std::move(result)};
884 std::vector<std::shared_ptr<array>> result(values_.size());
886 std::transform(values_.begin(), values_.end(), result.begin(),
887 [&](std::shared_ptr<base> v) -> std::shared_ptr<array> {
889 return std::static_pointer_cast<array>(v);
890 return std::shared_ptr<array>{};
902 if (values_.empty() || values_[0]->as<T>())
904 values_.push_back(val);
917 if (values_.empty() || values_[0]->is_array())
919 values_.push_back(val);
943 if (values_.empty() || values_[0]->as<T>())
945 return values_.insert(position,
value);
958 if (values_.empty() || values_[0]->is_array())
960 return values_.insert(position, value);
975 return insert(position,
make_value(std::forward<T>(val)));
983 return values_.erase(position);
1003 #if defined(CPPTOML_NO_RTTI) 1004 array() :
base(base_type::ARRAY)
1012 template <
class InputIterator>
1013 array(InputIterator begin, InputIterator end) : values_{begin, end}
1018 array(
const array& obj) =
delete;
1019 array& operator=(
const array& obj) =
delete;
1026 struct make_shared_enabler :
public array
1028 make_shared_enabler()
1034 return std::make_shared<make_shared_enabler>();
1052 array::get_array_of<array>()
const 1054 std::vector<std::shared_ptr<array>> result;
1055 result.reserve(values_.size());
1057 for (
const auto& val : values_)
1059 if (
auto v = val->as_array())
1060 result.push_back(v);
1065 return {std::move(result)};
1076 std::shared_ptr<base> clone()
const override;
1092 return array_.begin();
1097 return array_.begin();
1102 return array_.end();
1107 return array_.end();
1115 std::vector<std::shared_ptr<table>>&
get()
1120 const std::vector<std::shared_ptr<table>>&
get()
const 1130 array_.push_back(val);
1138 return array_.insert(position, value);
1146 return array_.erase(position);
1176 #if defined(CPPTOML_NO_RTTI) 1177 table_array(
bool is_inline =
false)
1178 :
base(base_type::TABLE_ARRAY), is_inline_(is_inline)
1189 table_array(
const table_array& obj) =
delete;
1190 table_array& operator=(
const table_array& rhs) =
delete;
1193 const bool is_inline_ =
false;
1198 struct make_shared_enabler :
public table_array
1200 make_shared_enabler(
bool mse_is_inline) : table_array(mse_is_inline)
1206 return std::make_shared<make_shared_enabler>(is_inline);
1222 typename std::enable_if<!std::is_floating_point<T>::value
1223 && std::is_signed<T>::value,
1227 if (
auto v = elem->as<int64_t>())
1229 if (v->get() < (std::numeric_limits<T>::min)())
1230 throw std::underflow_error{
1231 "T cannot represent the value requested in get"};
1233 if (v->get() > (std::numeric_limits<T>::max)())
1234 throw std::overflow_error{
1235 "T cannot represent the value requested in get"};
1237 return {
static_cast<T
>(v->get())};
1246 typename std::enable_if<!std::is_same<T, bool>::value
1247 && std::is_unsigned<T>::value,
1251 if (
auto v = elem->as<int64_t>())
1254 throw std::underflow_error{
"T cannot store negative value in get"};
1256 if (static_cast<uint64_t>(v->get()) > (std::numeric_limits<T>::max)())
1257 throw std::overflow_error{
1258 "T cannot represent the value requested in get"};
1260 return {
static_cast<T
>(v->get())};
1269 typename std::enable_if<!std::is_integral<T>::value
1270 || std::is_same<T, bool>::value,
1274 if (
auto v = elem->as<T>())
1290 friend class table_array;
1293 std::shared_ptr<base> clone()
const override;
1307 return map_.begin();
1312 return map_.begin();
1332 return map_.empty();
1340 return map_.find(key) != map_.end();
1350 return resolve_qualified(key);
1357 std::shared_ptr<base>
get(
const std::string& key)
const 1359 return map_.at(key);
1371 std::shared_ptr<base> p;
1372 resolve_qualified(key, &p);
1379 std::shared_ptr<table>
get_table(
const std::string& key)
const 1381 if (contains(key) &&
get(key)->is_table())
1382 return std::static_pointer_cast<table>(
get(key));
1392 if (contains_qualified(key) && get_qualified(key)->is_table())
1393 return std::static_pointer_cast<table>(get_qualified(key));
1400 std::shared_ptr<array>
get_array(
const std::string& key)
const 1404 return get(key)->as_array();
1412 if (!contains_qualified(key))
1414 return get_qualified(key)->as_array();
1424 return get(key)->as_table_array();
1431 std::shared_ptr<table_array>
1434 if (!contains_qualified(key))
1436 return get_qualified(key)->as_table_array();
1448 return get_impl<T>(
get(key));
1450 catch (
const std::out_of_range&)
1466 return get_impl<T>(get_qualified(key));
1468 catch (
const std::out_of_range&)
1487 if (
auto v = get_array(key))
1489 std::vector<T> result;
1490 result.reserve(v->get().size());
1492 for (
const auto& b : v->get())
1494 if (
auto val = b->as<T>())
1495 result.push_back(val->get());
1499 return {std::move(result)};
1519 if (
auto v = get_array_qualified(key))
1521 std::vector<T> result;
1522 result.reserve(v->get().size());
1524 for (
const auto& b : v->get())
1526 if (
auto val = b->as<T>())
1527 result.push_back(val->get());
1531 return {std::move(result)};
1540 void insert(
const std::string& key,
const std::shared_ptr<base>&
value)
1553 insert(key,
make_value(std::forward<T>(val)));
1565 #if defined(CPPTOML_NO_RTTI) 1566 table() :
base(base_type::TABLE)
1577 table(
const table& obj) =
delete;
1578 table& operator=(
const table& rhs) =
delete;
1581 char separator)
const 1583 std::vector<std::string> result;
1584 std::string::size_type p = 0;
1585 std::string::size_type q;
1586 while ((q = value.find(separator, p)) != std::string::npos)
1588 result.emplace_back(value, p, q - p);
1591 result.emplace_back(value, p);
1601 std::shared_ptr<base>* p =
nullptr)
const 1603 auto parts = split(key,
'.');
1604 auto last_key = parts.back();
1607 auto cur_table =
this;
1608 for (
const auto& part : parts)
1610 cur_table = cur_table->get_table(part).get();
1616 throw std::out_of_range{key +
" is not a valid key"};
1621 return cur_table->map_.count(last_key) != 0;
1623 *p = cur_table->map_.at(last_key);
1641 table::get_array_of<array>(
const std::string& key)
const 1643 if (
auto v = get_array(key))
1645 std::vector<std::shared_ptr<array>> result;
1646 result.reserve(v->get().size());
1648 for (
const auto& b : v->get())
1650 if (
auto val = b->as_array())
1651 result.push_back(val);
1656 return {std::move(result)};
1673 table::get_qualified_array_of<array>(
const std::string& key)
const 1675 if (
auto v = get_array_qualified(key))
1677 std::vector<std::shared_ptr<array>> result;
1678 result.reserve(v->get().size());
1680 for (
const auto& b : v->get())
1682 if (
auto val = b->as_array())
1683 result.push_back(val);
1688 return {std::move(result)};
1696 struct make_shared_enabler :
public table
1698 make_shared_enabler()
1704 return std::make_shared<make_shared_enabler>();
1725 result->reserve(values_.size());
1726 for (
const auto& ptr : values_)
1727 result->values_.push_back(ptr->clone());
1734 result->reserve(array_.size());
1735 for (
const auto& ptr : array_)
1736 result->array_.push_back(ptr->clone()->as_table());
1743 for (
const auto& pr : map_)
1744 result->insert(pr.first, pr.second->clone());
1759 :
std::runtime_error{err +
" at line " + std::to_string(line_number)}
1766 return c >=
'0' && c <=
'9';
1771 return is_number(c) || (c >=
'a' && c <= 'f') || (c >=
'A' && c <=
'F');
1777 template <
class OnError>
1781 consumer(std::string::iterator& it,
const std::string::iterator& end,
1783 : it_(it), end_(end), on_error_(
std::forward<OnError>(on_error))
1790 if (it_ == end_ || *it_ != c)
1795 template <std::
size_t N>
1798 std::for_each(std::begin(str), std::end(str) - 1,
1799 [&](
char c) { (*this)(c); });
1804 if (it_ == end_ || (*it_ != a && *it_ != b))
1812 for (
int i = 0; i < len; ++i)
1816 val = 10 * val + (*it_++ -
'0');
1832 template <
class OnError>
1834 const std::string::iterator& end,
1844 inline std::istream&
getline(std::istream& input, std::string& line)
1848 std::istream::sentry sentry{input,
true};
1849 auto sb = input.rdbuf();
1853 auto c = sb->sbumpc();
1856 if (sb->sgetc() ==
'\n')
1863 if (c == std::istream::traits_type::eof())
1866 input.setstate(std::ios::eofbit);
1870 line.push_back(static_cast<char>(c));
1884 parser(std::istream& stream) : input_(stream)
1899 table* curr_table = root.get();
1904 auto it = line_.begin();
1905 auto end = line_.end();
1906 consume_whitespace(it, end);
1907 if (it == end || *it ==
'#')
1911 curr_table = root.
get();
1912 parse_table(it, end, curr_table);
1916 parse_key_value(it, end, curr_table);
1917 consume_whitespace(it, end);
1918 eol_or_comment(it, end);
1925 #if defined _MSC_VER 1926 __declspec(noreturn)
1927 #elif defined __GNUC__ 1928 __attribute__((noreturn))
1936 const std::string::iterator& end, table*& curr_table)
1941 throw_parse_exception(
"Unexpected end of table");
1943 parse_table_array(it, end, curr_table);
1945 parse_single_table(it, end, curr_table);
1949 const std::string::iterator& end,
1952 if (it == end || *it ==
']')
1953 throw_parse_exception(
"Table name cannot be empty");
1955 std::string full_table_name;
1956 bool inserted =
false;
1958 auto key_end = [](
char c) {
return c ==
']'; };
1960 auto key_part_handler = [&](
const std::string& part) {
1962 throw_parse_exception(
"Empty component of table name");
1964 if (!full_table_name.empty())
1965 full_table_name +=
'.';
1966 full_table_name += part;
1971 auto b = curr_table->
get(part);
1974 std::shared_ptr<base> b = curr_table->
get(part);
1977 curr_table = static_cast<table*>(b.get());
1978 else if (b->is_table_array())
1979 curr_table = std::static_pointer_cast<table_array>(b)
1984 throw_parse_exception(
"Key " + full_table_name
1985 +
"already exists as a value");
1991 curr_table =
static_cast<table*
>(curr_table->
get(part).get());
1995 key_part_handler(parse_key(it, end, key_end, key_part_handler));
1998 throw_parse_exception(
1999 "Unterminated table declaration; did you forget a ']'?");
2003 std::string errmsg{
"Unexpected character in table definition: "};
2007 throw_parse_exception(errmsg);
2014 = [](
const std::pair<
const std::string&,
2015 const std::shared_ptr<base>&>& p) {
2016 return p.second->is_value();
2023 if (curr_table->
empty()
2024 || std::any_of(curr_table->
begin(), curr_table->
end(),
2027 throw_parse_exception(
"Redefinition of table " 2033 consume_whitespace(it, end);
2034 eol_or_comment(it, end);
2038 const std::string::iterator& end, table*& curr_table)
2041 if (it == end || *it ==
']')
2042 throw_parse_exception(
"Table array name cannot be empty");
2044 auto key_end = [](
char c) {
return c ==
']'; };
2046 std::string full_ta_name;
2047 auto key_part_handler = [&](
const std::string& part) {
2049 throw_parse_exception(
"Empty component of table array name");
2051 if (!full_ta_name.empty())
2052 full_ta_name +=
'.';
2053 full_ta_name += part;
2058 auto b = curr_table->
get(part);
2061 std::shared_ptr<base> b = curr_table->
get(part);
2067 if (it != end && *it ==
']')
2069 if (!b->is_table_array())
2071 throw_parse_exception(
"Key " + full_ta_name
2072 +
" is not a table array");
2075 auto v = b->as_table_array();
2079 throw_parse_exception(
"Static array " + full_ta_name
2080 +
" cannot be appended to");
2084 curr_table = v->
get().back().get();
2090 curr_table = static_cast<table*>(b.get());
2091 else if (b->is_table_array())
2092 curr_table = std::static_pointer_cast<table_array>(b)
2097 throw_parse_exception(
"Key " + full_ta_name
2098 +
" already exists as a value");
2106 if (it != end && *it ==
']')
2109 auto arr = std::static_pointer_cast<table_array>(
2110 curr_table->
get(part));
2112 curr_table = arr->
get().back().get();
2120 =
static_cast<table*
>(curr_table->
get(part).get());
2125 key_part_handler(parse_key(it, end, key_end, key_part_handler));
2129 throw_parse_exception(
"Unterminated table array name");
2134 consume_whitespace(it, end);
2135 eol_or_comment(it, end);
2141 auto key_end = [](
char c) {
return c ==
'='; };
2143 auto key_part_handler = [&](
const std::string& part) {
2149 auto val = curr_table->
get(part);
2150 if (val->is_table())
2152 curr_table =
static_cast<table*
>(val.get());
2156 throw_parse_exception(
"Key " + part
2157 +
" already exists as a value");
2163 curr_table->
insert(part, newtable);
2164 curr_table = newtable.
get();
2168 auto key = parse_key(it, end, key_end, key_part_handler);
2171 throw_parse_exception(
"Key " + key +
" already present");
2172 if (it == end || *it !=
'=')
2173 throw_parse_exception(
"Value must follow after a '='");
2175 consume_whitespace(it, end);
2176 curr_table->
insert(key, parse_value(it, end));
2177 consume_whitespace(it, end);
2180 template <
class KeyEndFinder,
class KeyPartHandler>
2182 parse_key(std::string::iterator& it,
const std::string::iterator& end,
2183 KeyEndFinder&& key_end, KeyPartHandler&& key_part_handler)
2186 while (it != end && !key_end(*it))
2188 auto part = parse_simple_key(it, end);
2189 consume_whitespace(it, end);
2191 if (it == end || key_end(*it))
2198 std::string errmsg{
"Unexpected character in key: "};
2202 throw_parse_exception(errmsg);
2205 key_part_handler(part);
2211 throw_parse_exception(
"Unexpected end of key");
2215 const std::string::iterator& end)
2217 consume_whitespace(it, end);
2220 throw_parse_exception(
"Unexpected end of key (blank key?)");
2222 if (*it ==
'"' || *it ==
'\'')
2224 return string_literal(it, end, *it);
2228 auto bke = std::find_if(it, end, [](
char c) {
2229 return c ==
'.' || c ==
'=' || c ==
']';
2231 return parse_bare_key(it, bke);
2236 const std::string::iterator& end)
2240 throw_parse_exception(
"Bare key missing name");
2245 consume_backwards_whitespace(key_end, it);
2247 std::string key{it, key_end};
2249 if (std::find(it, key_end,
'#') != key_end)
2251 throw_parse_exception(
"Bare key " + key +
" cannot contain #");
2254 if (std::find_if(it, key_end,
2255 [](
char c) {
return c ==
' ' || c ==
'\t'; })
2258 throw_parse_exception(
"Bare key " + key
2259 +
" cannot contain whitespace");
2262 if (std::find_if(it, key_end,
2263 [](
char c) {
return c ==
'[' || c ==
']'; })
2266 throw_parse_exception(
"Bare key " + key
2267 +
" cannot contain '[' or ']'");
2289 std::string::iterator& end)
2291 parse_type type = determine_value_type(it, end);
2294 case parse_type::STRING:
2295 return parse_string(it, end);
2296 case parse_type::LOCAL_TIME:
2297 return parse_time(it, end);
2298 case parse_type::LOCAL_DATE:
2299 case parse_type::LOCAL_DATETIME:
2300 case parse_type::OFFSET_DATETIME:
2301 return parse_date(it, end);
2302 case parse_type::INT:
2303 case parse_type::FLOAT:
2304 return parse_number(it, end);
2305 case parse_type::BOOL:
2306 return parse_bool(it, end);
2307 case parse_type::ARRAY:
2308 return parse_array(it, end);
2309 case parse_type::INLINE_TABLE:
2310 return parse_inline_table(it, end);
2312 throw_parse_exception(
"Failed to parse value");
2317 const std::string::iterator& end)
2321 throw_parse_exception(
"Failed to parse value type");
2323 if (*it ==
'"' || *it ==
'\'')
2325 return parse_type::STRING;
2327 else if (is_time(it, end))
2329 return parse_type::LOCAL_TIME;
2331 else if (
auto dtype = date_type(it, end))
2335 else if (
is_number(*it) || *it ==
'-' || *it ==
'+' 2336 || (*it ==
'i' && it + 1 != end && it[1] ==
'n' 2337 && it + 2 != end && it[2] ==
'f')
2338 || (*it ==
'n' && it + 1 != end && it[1] ==
'a' 2339 && it + 2 != end && it[2] ==
'n'))
2341 return determine_number_type(it, end);
2343 else if (*it ==
't' || *it ==
'f')
2345 return parse_type::BOOL;
2347 else if (*it ==
'[')
2349 return parse_type::ARRAY;
2351 else if (*it ==
'{')
2353 return parse_type::INLINE_TABLE;
2355 throw_parse_exception(
"Failed to parse value type");
2359 const std::string::iterator& end)
2363 if (*check_it ==
'-' || *check_it ==
'+')
2366 if (check_it == end)
2367 throw_parse_exception(
"Malformed number");
2369 if (*check_it ==
'i' || *check_it ==
'n')
2370 return parse_type::FLOAT;
2372 while (check_it != end &&
is_number(*check_it))
2374 if (check_it != end && *check_it ==
'.')
2377 while (check_it != end &&
is_number(*check_it))
2379 return parse_type::FLOAT;
2383 return parse_type::INT;
2387 std::shared_ptr<value<std::string>>
parse_string(std::string::iterator& it,
2388 std::string::iterator& end)
2391 assert(delim ==
'"' || delim ==
'\'');
2397 if (check_it != end && *check_it == delim)
2400 if (check_it != end && *check_it == delim)
2403 return parse_multiline_string(it, end, delim);
2406 return make_value<std::string>(string_literal(it, end, delim));
2409 std::shared_ptr<value<std::string>>
2411 std::string::iterator& end,
char delim)
2413 std::stringstream ss;
2415 auto is_ws = [](
char c) {
return c ==
' ' || c ==
'\t'; };
2417 bool consuming =
false;
2418 std::shared_ptr<value<std::string>> ret;
2420 auto handle_line = [&](std::string::iterator& local_it,
2421 std::string::iterator& local_end) {
2424 local_it = std::find_if_not(local_it, local_end, is_ws);
2427 if (local_it == local_end)
2433 while (local_it != local_end)
2436 if (delim ==
'"' && *local_it ==
'\\')
2438 auto check = local_it;
2442 consume_whitespace(
check, local_end);
2443 if (
check == local_end)
2449 ss << parse_escape_code(local_it, local_end);
2454 if (std::distance(local_it, local_end) >= 3)
2456 auto check = local_it;
2459 && *
check++ == delim)
2462 ret = make_value<std::string>(ss.str());
2472 handle_line(it, end);
2484 handle_line(it, end);
2493 throw_parse_exception(
"Unterminated multi-line basic string");
2497 const std::string::iterator& end,
char delim)
2504 if (delim ==
'"' && *it ==
'\\')
2506 val += parse_escape_code(it, end);
2508 else if (*it == delim)
2511 consume_whitespace(it, end);
2519 throw_parse_exception(
"Unterminated string literal");
2523 const std::string::iterator& end)
2527 throw_parse_exception(
"Invalid escape sequence");
2533 else if (*it ==
't')
2537 else if (*it ==
'n')
2541 else if (*it ==
'f')
2545 else if (*it ==
'r')
2549 else if (*it ==
'"')
2553 else if (*it ==
'\\')
2557 else if (*it ==
'u' || *it ==
'U')
2559 return parse_unicode(it, end);
2563 throw_parse_exception(
"Invalid escape sequence");
2566 return std::string(1, value);
2570 const std::string::iterator& end)
2572 bool large = *it++ ==
'U';
2573 auto codepoint = parse_hex(it, end, large ? 0x10000000 : 0x1000);
2575 if ((codepoint > 0xd7ff && codepoint < 0xe000) || codepoint > 0x10ffff)
2577 throw_parse_exception(
2578 "Unicode escape sequence is not a Unicode scalar value");
2583 if (codepoint <= 0x7f)
2587 result +=
static_cast<char>(codepoint & 0x7f);
2589 else if (codepoint <= 0x7ff)
2597 result +=
static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f));
2602 result +=
static_cast<char>(0x80 | (codepoint & 0x3f));
2604 else if (codepoint <= 0xffff)
2612 result +=
static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f));
2613 result +=
static_cast<char>(0x80 | ((codepoint >> 6) & 0x1f));
2614 result +=
static_cast<char>(0x80 | (codepoint & 0x3f));
2624 result +=
static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07));
2625 result +=
static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f));
2626 result +=
static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f));
2627 result +=
static_cast<char>(0x80 | (codepoint & 0x3f));
2633 const std::string::iterator& end, uint32_t place)
2639 throw_parse_exception(
"Unexpected end of unicode sequence");
2642 throw_parse_exception(
"Invalid unicode escape sequence");
2644 value += place * hex_to_digit(*it++);
2653 return static_cast<uint32_t
>(c -
'0');
2655 +
static_cast<uint32_t
>(c
2656 - ((c >=
'a' && c <=
'f') ?
'a' :
'A'));
2660 const std::string::iterator& end)
2663 auto check_end = find_end_of_number(it, end);
2665 auto eat_sign = [&]() {
2666 if (check_it != end && (*check_it ==
'-' || *check_it ==
'+'))
2670 auto check_no_leading_zero = [&]() {
2671 if (check_it != end && *check_it ==
'0' && check_it + 1 != check_end
2672 && check_it[1] !=
'.')
2674 throw_parse_exception(
"Numbers may not have leading zeros");
2678 auto eat_digits = [&](bool (*check_char)(char)) {
2679 auto beg = check_it;
2680 while (check_it != end && check_char(*check_it))
2683 if (check_it != end && *check_it ==
'_')
2686 if (check_it == end || !check_char(*check_it))
2687 throw_parse_exception(
"Malformed number");
2691 if (check_it == beg)
2692 throw_parse_exception(
"Malformed number");
2695 auto eat_hex = [&]() { eat_digits(&
is_hex); };
2697 auto eat_numbers = [&]() { eat_digits(&
is_number); };
2699 if (check_it != end && *check_it ==
'0' && check_it + 1 != check_end
2700 && (check_it[1] ==
'x' || check_it[1] ==
'o' || check_it[1] ==
'b'))
2703 char base = *check_it;
2708 return parse_int(it, check_it, 16);
2710 else if (base ==
'o')
2712 auto start = check_it;
2714 auto val = parse_int(start, check_it, 8,
"0");
2720 auto start = check_it;
2722 auto val = parse_int(start, check_it, 2);
2729 check_no_leading_zero();
2731 if (check_it != end && check_it + 1 != end && check_it + 2 != end)
2733 if (check_it[0] ==
'i' && check_it[1] ==
'n' && check_it[2] ==
'f')
2735 auto val = std::numeric_limits<double>::infinity();
2741 else if (check_it[0] ==
'n' && check_it[1] ==
'a' 2742 && check_it[2] ==
'n')
2744 auto val = std::numeric_limits<double>::quiet_NaN();
2755 && (*check_it ==
'.' || *check_it ==
'e' || *check_it ==
'E'))
2757 bool is_exp = *check_it ==
'e' || *check_it ==
'E';
2760 if (check_it == end)
2761 throw_parse_exception(
"Floats must have trailing digits");
2763 auto eat_exp = [&]() {
2765 check_no_leading_zero();
2774 if (!is_exp && check_it != end
2775 && (*check_it ==
'e' || *check_it ==
'E'))
2781 return parse_float(it, check_it);
2785 return parse_int(it, check_it);
2789 std::shared_ptr<value<int64_t>>
parse_int(std::string::iterator& it,
2790 const std::string::iterator& end,
2792 const char* prefix =
"")
2794 std::string v{it, end};
2796 v.erase(std::remove(v.begin(), v.end(),
'_'), v.end());
2800 return make_value<int64_t>(std::stoll(v,
nullptr,
base));
2802 catch (
const std::invalid_argument& ex)
2804 throw_parse_exception(
"Malformed number (invalid argument: " 2805 + std::string{ex.what()} +
")");
2807 catch (
const std::out_of_range& ex)
2809 throw_parse_exception(
"Malformed number (out of range: " 2810 + std::string{ex.what()} +
")");
2815 const std::string::iterator& end)
2817 std::string v{it, end};
2818 v.erase(std::remove(v.begin(), v.end(),
'_'), v.end());
2820 char decimal_point = std::localeconv()->decimal_point[0];
2821 std::replace(v.begin(), v.end(),
'.', decimal_point);
2824 return make_value<double>(std::stod(v));
2826 catch (
const std::invalid_argument& ex)
2828 throw_parse_exception(
"Malformed number (invalid argument: " 2829 + std::string{ex.what()} +
")");
2831 catch (
const std::out_of_range& ex)
2833 throw_parse_exception(
"Malformed number (out of range: " 2834 + std::string{ex.what()} +
")");
2838 std::shared_ptr<value<bool>>
parse_bool(std::string::iterator& it,
2839 const std::string::iterator& end)
2842 throw_parse_exception(
"Attempted to parse invalid boolean value");
2848 return make_value<bool>(
true);
2850 else if (*it ==
'f')
2853 return make_value<bool>(
false);
2861 std::string::iterator end)
2863 auto ret = std::find_if(it, end, [](
char c) {
2864 return !
is_number(c) && c !=
'_' && c !=
'.' && c !=
'e' && c !=
'E' 2865 && c !=
'-' && c !=
'+' && c !=
'x' && c !=
'o' && c !=
'b';
2867 if (ret != end && ret + 1 != end && ret + 2 != end)
2869 if ((ret[0] ==
'i' && ret[1] ==
'n' && ret[2] ==
'f')
2870 || (ret[0] ==
'n' && ret[1] ==
'a' && ret[2] ==
'n'))
2879 std::string::iterator end)
2881 auto end_of_date = std::find_if(it, end, [](
char c) {
2884 if (end_of_date != end && *end_of_date ==
' ' && end_of_date + 1 != end
2887 return std::find_if(end_of_date, end, [](
char c) {
2888 return !
is_number(c) && c !=
'T' && c !=
'Z' && c !=
':' 2889 && c !=
'-' && c !=
'+' && c !=
'.';
2894 std::string::iterator end)
2896 return std::find_if(it, end, [](
char c) {
2897 return !
is_number(c) && c !=
':' && c !=
'.';
2902 const std::string::iterator& end)
2904 auto time_end = find_end_of_time(it, end);
2907 it, time_end, [&]() { throw_parse_exception(
"Malformed time"); });
2911 ltime.hour = eat.eat_digits(2);
2913 ltime.minute = eat.eat_digits(2);
2915 ltime.second = eat.eat_digits(2);
2918 if (it != time_end && *it ==
'.')
2921 while (it != time_end &&
is_number(*it))
2923 ltime.microsecond += power * (*it++ -
'0');
2929 throw_parse_exception(
"Malformed time");
2934 std::shared_ptr<value<local_time>>
2935 parse_time(std::string::iterator& it,
const std::string::iterator& end)
2941 const std::string::iterator& end)
2943 auto date_end = find_end_of_date(it, end);
2946 it, date_end, [&]() { throw_parse_exception(
"Malformed date"); });
2949 ldate.year = eat.eat_digits(4);
2951 ldate.month = eat.eat_digits(2);
2953 ldate.day = eat.eat_digits(2);
2958 eat.eat_or(
'T',
' ');
2961 static_cast<local_date&
>(ldt) = ldate;
2962 static_cast<local_time&
>(ldt) = read_time(it, date_end);
2968 static_cast<local_datetime&
>(dt) = ldt;
2972 if (*it ==
'+' || *it ==
'-')
2974 auto plus = *it ==
'+';
2977 hoff = eat.eat_digits(2);
2980 moff = eat.eat_digits(2);
2983 else if (*it ==
'Z')
2989 throw_parse_exception(
"Malformed date");
2995 std::string::iterator& end)
3006 skip_whitespace_and_comments(it, end);
3015 auto val_end = std::find_if(
3016 it, end, [](
char c) {
return c ==
',' || c ==
']' || c ==
'#'; });
3017 parse_type type = determine_value_type(it, val_end);
3020 case parse_type::STRING:
3021 return parse_value_array<std::string>(it, end);
3022 case parse_type::LOCAL_TIME:
3023 return parse_value_array<local_time>(it, end);
3024 case parse_type::LOCAL_DATE:
3025 return parse_value_array<local_date>(it, end);
3026 case parse_type::LOCAL_DATETIME:
3027 return parse_value_array<local_datetime>(it, end);
3028 case parse_type::OFFSET_DATETIME:
3029 return parse_value_array<offset_datetime>(it, end);
3030 case parse_type::INT:
3031 return parse_value_array<int64_t>(it, end);
3032 case parse_type::FLOAT:
3033 return parse_value_array<double>(it, end);
3034 case parse_type::BOOL:
3035 return parse_value_array<bool>(it, end);
3036 case parse_type::ARRAY:
3039 case parse_type::INLINE_TABLE:
3040 return parse_object_array<table_array>(
3043 throw_parse_exception(
"Unable to parse array");
3047 template <
class Value>
3049 std::string::iterator& end)
3052 while (it != end && *it !=
']')
3054 auto val = parse_value(it, end);
3055 if (
auto v = val->as<Value>())
3056 arr->get().push_back(val);
3058 throw_parse_exception(
"Arrays must be homogeneous");
3059 skip_whitespace_and_comments(it, end);
3063 skip_whitespace_and_comments(it, end);
3070 template <
class Object,
class Function>
3072 std::string::iterator& it,
3073 std::string::iterator& end)
3075 auto arr = detail::make_element<Object>();
3077 while (it != end && *it !=
']')
3080 throw_parse_exception(
"Unexpected character in array");
3082 arr->get().push_back(((*this).*fun)(it, end));
3083 skip_whitespace_and_comments(it, end);
3085 if (it == end || *it !=
',')
3089 skip_whitespace_and_comments(it, end);
3092 if (it == end || *it !=
']')
3093 throw_parse_exception(
"Unterminated array");
3100 std::string::iterator& end)
3107 throw_parse_exception(
"Unterminated inline table");
3109 consume_whitespace(it, end);
3110 if (it != end && *it !=
'}')
3112 parse_key_value(it, end, tbl.get());
3113 consume_whitespace(it, end);
3115 }
while (*it ==
',');
3117 if (it == end || *it !=
'}')
3118 throw_parse_exception(
"Unterminated inline table");
3121 consume_whitespace(it, end);
3127 std::string::iterator& end)
3129 consume_whitespace(start, end);
3130 while (start == end || *start ==
'#')
3133 throw_parse_exception(
"Unclosed array");
3135 start = line_.begin();
3137 consume_whitespace(start, end);
3142 const std::string::iterator& end)
3144 while (it != end && (*it ==
' ' || *it ==
'\t'))
3149 const std::string::iterator& front)
3151 while (back != front && (*back ==
' ' || *back ==
'\t'))
3156 const std::string::iterator& end)
3158 if (it != end && *it !=
'#')
3159 throw_parse_exception(
"Unidentified trailing character '" 3161 +
"'---did you forget a '#'?");
3165 const std::string::iterator& end)
3167 auto time_end = find_end_of_time(it, end);
3168 auto len = std::distance(it, time_end);
3173 if (it[2] !=
':' || it[5] !=
':')
3177 return it[8] ==
'.' && len > 9;
3183 const std::string::iterator& end)
3185 auto date_end = find_end_of_date(it, end);
3186 auto len = std::distance(it, date_end);
3191 if (it[4] !=
'-' || it[7] !=
'-')
3194 if (len >= 19 && (it[10] ==
'T' || it[10] ==
' ')
3195 && is_time(it + 11, date_end))
3198 auto time_end = find_end_of_time(it + 11, date_end);
3199 if (time_end == date_end)
3200 return {parse_type::LOCAL_DATETIME};
3202 return {parse_type::OFFSET_DATETIME};
3207 return {parse_type::LOCAL_DATE};
3215 std::size_t line_number_ = 0;
3222 inline std::shared_ptr<table>
parse_file(
const std::string& filename)
3224 #if defined(BOOST_NOWIDE_FSTREAM_INCLUDED_HPP) 3225 boost::nowide::ifstream file{filename.c_str()};
3226 #elif defined(NOWIDE_FSTREAM_INCLUDED_HPP) 3227 nowide::ifstream file{filename.c_str()};
3229 std::ifstream file{filename};
3231 if (!file.is_open())
3237 template <
class... Ts>
3243 template <
class Visitor,
class... Args>
3250 template <
class T,
class... Ts>
3253 template <
class Visitor,
class... Args>
3254 static void accept(
const base& b, Visitor&& visitor, Args&&... args)
3256 if (
auto v = b.
as<T>())
3258 visitor.visit(*v, std::forward<Args>(args)...);
3263 std::forward<Args>(args)...);
3272 template <
class Visitor,
class... Args>
3277 using value_acceptor
3278 =
value_accept<std::string, int64_t, double, bool, local_date,
3279 local_time, local_datetime, offset_datetime>;
3280 value_acceptor::accept(*
this, std::forward<Visitor>(visitor),
3281 std::forward<Args>(args)...);
3283 else if (is_table())
3285 visitor.visit(static_cast<const table&>(*
this),
3286 std::forward<Args>(args)...);
3288 else if (is_array())
3290 visitor.visit(static_cast<const array&>(*
this),
3291 std::forward<Args>(args)...);
3293 else if (is_table_array())
3295 visitor.visit(static_cast<const table_array&>(*
this),
3296 std::forward<Args>(args)...);
3311 : stream_(s), indent_(indent_space), has_naked_endline_(false)
3329 void visit(
const table& t,
bool in_array =
false)
3331 write_table_header(in_array);
3332 std::vector<std::string> values;
3333 std::vector<std::string> tables;
3335 for (
const auto& i : t)
3337 if (i.second->is_table() || i.second->is_table_array())
3339 tables.push_back(i.first);
3343 values.push_back(i.first);
3347 for (
unsigned int i = 0; i < values.size(); ++i)
3349 path_.push_back(values[i]);
3354 write_table_item_header(*t.get(values[i]));
3355 t.get(values[i])->accept(*
this,
false);
3359 for (
unsigned int i = 0; i < tables.size(); ++i)
3361 path_.push_back(tables[i]);
3363 if (values.size() > 0 || i > 0)
3366 write_table_item_header(*t.get(tables[i]));
3367 t.get(tables[i])->accept(*
this,
false);
3377 void visit(
const array& a,
bool =
false)
3381 for (
unsigned int i = 0; i < a.
get().size(); ++i)
3386 if (a.
get()[i]->is_array())
3388 a.
get()[i]->as_array()->accept(*
this,
true);
3392 a.
get()[i]->accept(*
this,
true);
3402 void visit(
const table_array& t,
bool =
false)
3404 for (
unsigned int j = 0; j < t.
get().size(); ++j)
3409 t.
get()[j]->accept(*
this,
true);
3421 for (
auto it = str.begin(); it != str.end(); ++it)
3427 else if (*it ==
'\t')
3431 else if (*it ==
'\n')
3435 else if (*it ==
'\f')
3439 else if (*it ==
'\r')
3443 else if (*it ==
'"')
3447 else if (*it ==
'\\')
3451 else if (static_cast<uint32_t>(*it) <= UINT32_C(0x001f))
3454 std::stringstream ss;
3455 ss << std::hex << static_cast<uint32_t>(*it);
3473 write(escape_string(v.
get()));
3482 std::stringstream ss;
3483 ss << std::showpoint
3484 << std::setprecision(std::numeric_limits<double>::max_digits10)
3487 auto double_str = ss.str();
3488 auto pos = double_str.find(
"e0");
3489 if (pos != std::string::npos)
3490 double_str.replace(pos, 2,
"e");
3491 pos = double_str.find(
"e-0");
3492 if (pos != std::string::npos)
3493 double_str.replace(pos, 3,
"e-");
3495 stream_ << double_str;
3496 has_naked_endline_ =
false;
3504 typename std::enable_if<
3505 is_one_of<T, int64_t, local_date, local_time, local_datetime,
3506 offset_datetime>
::value>::type
3517 write((v.
get() ?
"true" :
"false"));
3536 for (
unsigned int i = 0; i < path_.size(); ++i)
3543 if (path_[i].find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" 3544 "fghijklmnopqrstuvwxyz0123456789" 3546 == std::string::npos)
3553 write(escape_string(path_[i]));
3577 if (path_.back().find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" 3578 "fghijklmnopqrstuvwxyz0123456789" 3580 == std::string::npos)
3582 write(path_.back());
3587 write(escape_string(path_.back()));
3602 for (std::size_t i = 1; i < path_.size(); ++i)
3613 has_naked_endline_ =
false;
3621 if (!has_naked_endline_)
3624 has_naked_endline_ =
true;
3643 std::ostream& operator<<(std::ostream& stream, const value<T>& v)
3650 inline std::ostream&
operator<<(std::ostream& stream,
const table& t)
3657 inline std::ostream&
operator<<(std::ostream& stream,
const table_array& t)
3664 inline std::ostream&
operator<<(std::ostream& stream,
const array& a)
std::vector< std::shared_ptr< base > > values_
Definition: cpptoml.h:1021
std::shared_ptr< base > clone() const override
Definition: cpptoml.h:1740
option< parse_type > date_type(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:3182
bool resolve_qualified(const std::string &key, std::shared_ptr< base > *p=nullptr) const
Definition: cpptoml.h:1600
std::shared_ptr< base > get_qualified(const std::string &key) const
Definition: cpptoml.h:1369
Definition: cpptoml.h:777
iterator insert(iterator position, const std::shared_ptr< value< T >> &value)
Definition: cpptoml.h:941
void insert(const std::string &key, const std::shared_ptr< base > &value)
Definition: cpptoml.h:1540
std::istream & input_
Definition: cpptoml.h:3213
std::shared_ptr< value< T > > as()
Definition: cpptoml.h:683
iterator insert(iterator position, const std::shared_ptr< array > &value)
Definition: cpptoml.h:956
void reserve(size_type n)
Definition: cpptoml.h:1160
void push_back(const std::shared_ptr< value< T >> &val)
Definition: cpptoml.h:900
int minute
Definition: cpptoml.h:113
void parse_key_value(std::string::iterator &it, std::string::iterator &end, table *curr_table)
Definition: cpptoml.h:2138
array_of_trait< T >::return_type get_qualified_array_of(const std::string &key) const
Definition: cpptoml.h:1517
std::shared_ptr< table_array > make_element< table_array >()
Definition: cpptoml.h:1212
std::shared_ptr< table_array > as_table_array()
Definition: cpptoml.h:562
std::shared_ptr< array > get_array_qualified(const std::string &key) const
Definition: cpptoml.h:1410
consumer(std::string::iterator &it, const std::string::iterator &end, OnError &&on_error)
Definition: cpptoml.h:1781
std::string parse_escape_code(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2522
void parse_single_table(std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
Definition: cpptoml.h:1948
array_exception(const std::string &err)
Definition: cpptoml.h:772
void parse_table(std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
Definition: cpptoml.h:1935
static value_type construct(T &&val)
Definition: cpptoml.h:311
Definition: cpptoml.h:291
std::shared_ptr< base > clone() const override
Definition: cpptoml.h:1731
virtual bool is_table_array() const override
Definition: cpptoml.h:1110
std::enable_if< is_one_of< T, int64_t, local_date, local_time, local_datetime, offset_datetime >::value >::type write(const value< T > &v)
Definition: cpptoml.h:3507
void visit(const value< T > &v, bool=false)
Definition: cpptoml.h:3321
Definition: cpptoml.h:385
static void accept(const base &b, Visitor &&visitor, Args &&... args)
Definition: cpptoml.h:3254
void write(const value< std::string > &v)
Definition: cpptoml.h:3470
void visit(const table &t, bool in_array=false)
Definition: cpptoml.h:3329
const std::string indent_
Definition: cpptoml.h:3630
std::shared_ptr< array > make_array()
Definition: cpptoml.h:1024
static std::string escape_string(const std::string &str)
Definition: cpptoml.h:3418
void consume_backwards_whitespace(std::string::iterator &back, const std::string::iterator &front)
Definition: cpptoml.h:3148
std::shared_ptr< table > make_element< table >()
Definition: cpptoml.h:1710
std::shared_ptr< base > parse_number(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2659
int month
Definition: cpptoml.h:106
iterator erase(iterator position)
Definition: cpptoml.h:1144
std::ostream & os_
Definition: cpptoml.h:185
uint32_t parse_hex(std::string::iterator &it, const std::string::iterator &end, uint32_t place)
Definition: cpptoml.h:2632
std::size_t size_type
Definition: cpptoml.h:1078
std::shared_ptr< base > get(const std::string &key) const
Definition: cpptoml.h:1357
std::shared_ptr< array > make_element< array >()
Definition: cpptoml.h:1040
Definition: cpptoml.h:501
bool has_naked_endline_
Definition: cpptoml.h:3632
static value_type construct(T &&val)
Definition: cpptoml.h:345
int day
Definition: cpptoml.h:107
bool contains(const std::string &key) const
Definition: cpptoml.h:1338
std::shared_ptr< array > as_array()
Definition: cpptoml.h:544
std::shared_ptr< value< std::string > > parse_multiline_string(std::string::iterator &it, std::string::iterator &end, char delim)
Definition: cpptoml.h:2410
std::string::iterator find_end_of_date(std::string::iterator it, std::string::iterator end)
Definition: cpptoml.h:2878
bool is_time(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:3164
virtual bool is_table() const
Definition: cpptoml.h:519
const_iterator begin() const
Definition: cpptoml.h:806
int year
Definition: cpptoml.h:105
void clear()
Definition: cpptoml.h:989
std::vector< std::shared_ptr< table > >::const_iterator const_iterator
Definition: cpptoml.h:1088
std::shared_ptr< table_array > get_table_array(const std::string &key) const
Definition: cpptoml.h:1420
Definition: cpptoml.h:294
std::shared_ptr< table > make_table()
Definition: cpptoml.h:1694
T data_
Definition: cpptoml.h:654
static value_type construct(T &&val)
Definition: cpptoml.h:370
Definition: cpptoml.h:3304
virtual bool is_array() const override
Definition: cpptoml.h:784
iterator begin()
Definition: cpptoml.h:1090
std::shared_ptr< base > clone() const override
Definition: cpptoml.h:1717
T & get()
Definition: cpptoml.h:640
std::vector< std::shared_ptr< table > > array_
Definition: cpptoml.h:1192
T value_
Definition: cpptoml.h:100
int eat_digits(int len)
Definition: cpptoml.h:1809
virtual bool is_array() const
Definition: cpptoml.h:536
std::string::iterator find_end_of_number(std::string::iterator it, std::string::iterator end)
Definition: cpptoml.h:2860
parse_exception(const std::string &err, std::size_t line_number)
Definition: cpptoml.h:1758
std::string string_literal(std::string::iterator &it, const std::string::iterator &end, char delim)
Definition: cpptoml.h:2496
string_to_base_map::const_iterator const_iterator
Definition: cpptoml.h:1303
Definition: cpptoml.h:103
void write(const value< double > &v)
Definition: cpptoml.h:3480
const_iterator end() const
Definition: cpptoml.h:816
Definition: cpptoml.h:1778
typename std::decay< T >::type value_type
Definition: cpptoml.h:324
iterator begin()
Definition: cpptoml.h:801
Definition: cpptoml.h:1751
value(const T &val)
Definition: cpptoml.h:664
std::string line_
Definition: cpptoml.h:3214
parse_type determine_number_type(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2358
void eat_or(char a, char b)
Definition: cpptoml.h:1802
std::shared_ptr< base > at(size_t idx) const
Definition: cpptoml.h:837
void throw_parse_exception(const std::string &err)
Definition: cpptoml.h:1930
Definition: cpptoml.h:1878
std::shared_ptr< value< local_time > > parse_time(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2935
Definition: cpptoml.h:110
std::enable_if<!std::is_floating_point< T >::value &&std::is_signed< T >::value, option< T > >::type get_impl(const std::shared_ptr< base > &elem)
Definition: cpptoml.h:1225
std::shared_ptr< table > get_table_qualified(const std::string &key) const
Definition: cpptoml.h:1390
Definition: cpptoml.h:1287
std::shared_ptr< typename value_traits< T >::type > make_value(T &&val)
Definition: cpptoml.h:674
std::shared_ptr< value< std::string > > parse_string(std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:2387
std::shared_ptr< table > parse()
Definition: cpptoml.h:1895
virtual bool is_value() const
Definition: cpptoml.h:511
Definition: cpptoml.h:1070
int64_t value_type
Definition: cpptoml.h:341
const_iterator begin() const
Definition: cpptoml.h:1095
~fill_guard()
Definition: cpptoml.h:179
void push_back(T &&val, typename value_traits< T >::type *=0)
Definition: cpptoml.h:932
uint32_t hex_to_digit(char c)
Definition: cpptoml.h:2650
std::shared_ptr< T > make_element()
parser(std::istream &stream)
Definition: cpptoml.h:1884
static value_type construct(T &&val)
Definition: cpptoml.h:328
bool is_inline() const
Definition: cpptoml.h:1170
void write(const value< bool > &v)
Definition: cpptoml.h:3515
std::unordered_map< std::string, std::shared_ptr< base > > string_to_base_map
Definition: cpptoml.h:54
bool empty() const
Definition: cpptoml.h:1330
std::shared_ptr< base > clone() const override
Definition: cpptoml.h:1722
iterator begin()
Definition: cpptoml.h:1305
table_array(bool is_inline=false)
Definition: cpptoml.h:1183
std::shared_ptr< array > get_array(const std::string &key) const
Definition: cpptoml.h:1400
std::shared_ptr< table > get_table(const std::string &key) const
Definition: cpptoml.h:1379
void operator()(char c)
Definition: cpptoml.h:1788
std::shared_ptr< table_array > get_table_array_qualified(const std::string &key) const
Definition: cpptoml.h:1432
void eol_or_comment(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:3155
void visit(const table_array &t, bool=false)
Definition: cpptoml.h:3402
void reserve(size_type n)
Definition: cpptoml.h:997
std::vector< std::shared_ptr< base > >::const_iterator const_iterator
Definition: cpptoml.h:799
Definition: cpptoml.h:124
base()
Definition: cpptoml.h:599
int microsecond
Definition: cpptoml.h:115
std::istream & getline(std::istream &input, std::string &line)
Definition: cpptoml.h:1844
value(const make_shared_enabler &, const T &val)
Definition: cpptoml.h:626
std::shared_ptr< base > parse_value(std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:2288
const_iterator end() const
Definition: cpptoml.h:1105
void accept(Visitor &&visitor, Args &&... args) const
Definition: cpptoml.h:3273
pure character(:) function, allocatable check(yesno)
Definition: pt.f90:546
void erase(const std::string &key)
Definition: cpptoml.h:1559
std::ostream & stream_
Definition: cpptoml.h:3629
int hour
Definition: cpptoml.h:112
std::shared_ptr< base > parse_array(std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:2994
const T * operator->() const
Definition: cpptoml.h:85
void parse_table_array(std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
Definition: cpptoml.h:2037
Definition: cpptoml.h:284
std::shared_ptr< value< bool > > parse_bool(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2838
array_of_trait< T >::return_type get_array_of() const
Definition: cpptoml.h:862
std::string parse_unicode(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2569
std::shared_ptr< Object > parse_object_array(Function &&fun, char delim, std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:3071
T value_or(U &&alternative) const
Definition: cpptoml.h:91
std::shared_ptr< base > parse_date(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2940
bool contains_qualified(const std::string &key) const
Definition: cpptoml.h:1348
iterator erase(iterator position)
Definition: cpptoml.h:981
iterator end()
Definition: cpptoml.h:1315
toml_writer(std::ostream &s, const std::string &indent_space="\)
Definition: cpptoml.h:3310
Definition: cpptoml.h:266
parse_exception(const std::string &err)
Definition: cpptoml.h:1754
void insert(const std::string &key, T &&val, typename value_traits< T >::type *=0)
Definition: cpptoml.h:1550
std::shared_ptr< value< int64_t > > parse_int(std::string::iterator &it, const std::string::iterator &end, int base=10, const char *prefix="")
Definition: cpptoml.h:2789
std::shared_ptr< table > parse_inline_table(std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:3099
iterator insert(iterator position, const std::shared_ptr< table > &value)
Definition: cpptoml.h:1136
array_of_trait< T >::return_type get_array_of(const std::string &key) const
Definition: cpptoml.h:1485
option(T value)
Definition: cpptoml.h:70
table()
Definition: cpptoml.h:1571
int minute_offset
Definition: cpptoml.h:121
Definition: cpptoml.h:171
const_iterator begin() const
Definition: cpptoml.h:1310
void consume_whitespace(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:3141
Definition: cpptoml.h:769
void indent()
Definition: cpptoml.h:3600
std::string parse_key(std::string::iterator &it, const std::string::iterator &end, KeyEndFinder &&key_end, KeyPartHandler &&key_part_handler)
Definition: cpptoml.h:2182
bool is_table() const override
Definition: cpptoml.h:1325
std::vector< std::shared_ptr< table > >::iterator iterator
Definition: cpptoml.h:1083
std::string parse_simple_key(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2214
void visit(const array &a, bool=false)
Definition: cpptoml.h:3377
string_to_base_map::iterator iterator
Definition: cpptoml.h:1298
void write_table_header(bool in_array=false)
Definition: cpptoml.h:3523
std::vector< std::shared_ptr< table > > & get()
Definition: cpptoml.h:1115
void write(const T &v)
Definition: cpptoml.h:3610
std::vector< std::shared_ptr< base > > & get()
Definition: cpptoml.h:824
void push_back(const std::shared_ptr< array > &val)
Definition: cpptoml.h:915
local_time read_time(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2901
Definition: cpptoml.h:118
std::string::iterator find_end_of_time(std::string::iterator it, std::string::iterator end)
Definition: cpptoml.h:2893
std::vector< std::string > path_
Definition: cpptoml.h:3631
Definition: cpptoml.h:128
typename std::conditional< valid_value< typename std::decay< T >::type >::value, typename std::decay< T >::type, std::string >::type value_type
Definition: cpptoml.h:307
std::vector< std::string > split(const std::string &value, char separator) const
Definition: cpptoml.h:1580
std::shared_ptr< value< double > > parse_float(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2814
std::vector< std::shared_ptr< base > >::iterator iterator
Definition: cpptoml.h:794
Definition: cpptoml.h:3238
std::ostream & operator<<(std::ostream &os, const local_date &dt)
Definition: cpptoml.h:189
option()
Definition: cpptoml.h:65
void operator()(const char(&str)[N])
Definition: cpptoml.h:1796
std::ostream::char_type fill_
Definition: cpptoml.h:186
const std::string::iterator & end_
Definition: cpptoml.h:1828
consumer< OnError > make_consumer(std::string::iterator &it, const std::string::iterator &end, OnError &&on_error)
Definition: cpptoml.h:1833
void write_table_item_header(const base &b)
Definition: cpptoml.h:3571
std::string::iterator & it_
Definition: cpptoml.h:1827
void error()
Definition: cpptoml.h:1821
iterator insert(iterator position, T &&val, typename value_traits< T >::type *=0)
Definition: cpptoml.h:972
parse_type
Definition: cpptoml.h:2274
static void accept(const base &, Visitor &&, Args &&...)
Definition: cpptoml.h:3244
void skip_whitespace_and_comments(std::string::iterator &start, std::string::iterator &end)
Definition: cpptoml.h:3126
std::vector< std::shared_ptr< array > > nested_array() const
Definition: cpptoml.h:882
std::size_t size_type
Definition: cpptoml.h:789
option< T > get_qualified_as(const std::string &key) const
Definition: cpptoml.h:1462
std::shared_ptr< table > parse_file(const std::string &filename)
Definition: cpptoml.h:3222
int64_t value_type
Definition: cpptoml.h:366
std::shared_ptr< table_array > make_table_array(bool is_inline=false)
Definition: cpptoml.h:1196
Definition: cpptoml.h:281
string_to_base_map map_
Definition: cpptoml.h:1627
iterator end()
Definition: cpptoml.h:811
virtual bool is_table_array() const
Definition: cpptoml.h:554
fill_guard(std::ostream &os)
Definition: cpptoml.h:174
OnError on_error_
Definition: cpptoml.h:1829
array(InputIterator begin, InputIterator end)
Definition: cpptoml.h:1013
void endline()
Definition: cpptoml.h:3619
bool is_number(char c)
Definition: cpptoml.h:1764
std::shared_ptr< array > parse_value_array(std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:3048
iterator end()
Definition: cpptoml.h:1100
void clear()
Definition: cpptoml.h:1152
std::vector< std::shared_ptr< value< T > > > array_of() const
Definition: cpptoml.h:847
bool is_hex(char c)
Definition: cpptoml.h:1769
std::string parse_bare_key(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2235
Definition: cpptoml.h:612
const_iterator end() const
Definition: cpptoml.h:1320
int second
Definition: cpptoml.h:114
std::shared_ptr< table > as_table()
Definition: cpptoml.h:527
const T & operator*() const
Definition: cpptoml.h:80
option< T > get_as(const std::string &key) const
Definition: cpptoml.h:1444
parse_type determine_value_type(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2316
bool empty_
Definition: cpptoml.h:99
void push_back(const std::shared_ptr< table > &val)
Definition: cpptoml.h:1128
int hour_offset
Definition: cpptoml.h:120
bool is_value() const override
Definition: cpptoml.h:632