47#include <unordered_map>
52#if __cplusplus > 201103L
53#define CPPTOML_DEPRECATED(reason) [[deprecated(reason)]]
54#elif defined(__clang__)
55#define CPPTOML_DEPRECATED(reason) __attribute__((deprecated(reason)))
56#elif defined(__GNUG__)
57#define CPPTOML_DEPRECATED(reason) __attribute__((deprecated))
58#elif defined(_MSC_VER)
60#define CPPTOML_DEPRECATED(reason) __declspec(deprecated)
62#define CPPTOML_DEPRECATED(reason) [[deprecated(reason)]]
69#if defined(CPPTOML_USE_MAP)
81#define CPPTOML_NO_RTTI
82#define CPPTOML_NO_EXCEPTIONS
84#if defined(CPPTOML_NO_EXCEPTIONS)
86#define THROW_(exception, reason) die(reason, __FILE__, __LINE__)
87#define THROW2_(exception, reason, input_line) die(reason, input_line, __FILE__, __LINE__)
89[[noreturn]]
inline void die(
const std::string& reason,
const std::string& file,
const int line) {
90 std::cerr << file <<
":" << std::to_string(line) <<
": error: " << reason << std::endl;
94[[noreturn]]
inline void die(
const std::string& reason,
const int input_line,
const std::string& file,
const int line) {
95 std::cerr << file <<
":" << std::to_string(line) <<
": error: " << reason <<
" at line " << input_line << std::endl;
99#define THROW_(exception, reason) \
100 throw exception { reason }
101#define THROW2_(exception, reason, input_line) \
102 throw exception { reason, input_line }
155 dt.
year = t.tm_year + 1900;
156 dt.
month = t.tm_mon + 1;
163 strftime(buf, 16,
"%z", &t);
165 int offset = std::stoi(buf);
176 dt.
year = t.tm_year + 1900;
177 dt.
month = t.tm_mon + 1;
191 explicit fill_guard(std::ostream& os) : os_(os), fill_{os.fill()} {
207 os << setw(4) << dt.
year <<
"-" << setw(2) << dt.
month <<
"-" << setw(2) << dt.
day;
217 os << setw(2) << ltime.
hour <<
":" << setw(2) << ltime.
minute <<
":" << setw(2) << ltime.
second;
222 for(
int curr_us = ltime.
microsecond; curr_us; power /= 10) {
223 auto num = curr_us / power;
225 curr_us -= num * power;
253 return os << static_cast<const local_date&>(dt) <<
"T" <<
static_cast<const local_time&
>(dt);
257 return os << static_cast<const local_datetime&>(dt) <<
static_cast<const zone_offset&
>(dt);
260template <
class T,
class... Ts>
263template <
class T,
class V>
266template <
class T,
class V,
class... Ts>
276 :
is_one_of<T, std::string, int64_t, double, MBool, local_date, local_time, local_datetime, offset_datetime> {};
278template <
class T,
class Enable =
void>
288struct value_traits<T, typename std::enable_if<valid_value_or_string_convertible<T>::value>::type> {
289 using value_type =
typename std::conditional<valid_value<typename std::decay<T>::type>::value,
290 typename std::decay<T>::type, std::string>::type;
298struct value_traits<T, typename std::enable_if<!valid_value_or_string_convertible<T>::value
299 && std::is_floating_point<typename std::decay<T>::type>::value>::type> {
308struct value_traits<T, typename std::enable_if<!valid_value_or_string_convertible<T>::value
309 && std::is_signed<typename std::decay<T>::type>::value>::type> {
315 if(val < std::numeric_limits<int64_t>::min())
316 THROW_(std::underflow_error,
"constructed value cannot be "
317 "represented by a 64-bit signed "
320 if(val > std::numeric_limits<int64_t>::max())
321 THROW_(std::overflow_error,
"constructed value cannot be represented "
322 "by a 64-bit signed integer");
324 return static_cast<int64_t
>(val);
329struct value_traits<T, typename std::enable_if<!valid_value_or_string_convertible<T>::value
330 && std::is_unsigned<typename std::decay<T>::type>::value>::type> {
336 if(val >
static_cast<uint64_t
>(std::numeric_limits<int64_t>::max()))
337 THROW_(std::overflow_error,
"constructed value cannot be represented "
338 "by a 64-bit signed integer");
340 return static_cast<int64_t
>(val);
359inline std::shared_ptr<typename value_traits<T>::type>
make_value(T&& val);
366#if defined(CPPTOML_NO_RTTI)
412#ifdef MAIA_MS_COMPILER
453class base :
public std::enable_shared_from_this<base> {
457 virtual std::shared_ptr<base>
clone()
const = 0;
473 if(
is_table())
return std::static_pointer_cast<table>(shared_from_this());
485 if(
is_array())
return std::static_pointer_cast<array>(shared_from_this());
498 if(
is_table_array())
return std::static_pointer_cast<table_array>(shared_from_this());
507 std::shared_ptr<value<T>>
as();
510 std::shared_ptr<const value<T>>
as()
const;
512 template <
class Visitor,
class... Args>
513 void accept(Visitor&& visitor, Args&&... args)
const;
515#if defined(CPPTOML_NO_RTTI)
547#ifndef MAIA_MS_COMPILER
551 std::shared_ptr<base>
clone()
const override;
576#if defined(CPPTOML_NO_RTTI)
588std::shared_ptr<typename value_traits<T>::type>
make_value(T&& val) {
590 using enabler =
typename value_type::make_shared_enabler;
596#if defined(CPPTOML_NO_RTTI)
598 return std::static_pointer_cast<value<T>>(shared_from_this());
602 return std::dynamic_pointer_cast<value<T>>(shared_from_this());
610#if defined(CPPTOML_NO_RTTI)
611 if(
type() ==
base_type::FLOAT)
return std::static_pointer_cast<value<double>>(shared_from_this());
614 auto v = std::static_pointer_cast<value<int64_t>>(shared_from_this());
615 return make_value<double>(
static_cast<double>(v->get()));
618 if(
auto v = std::dynamic_pointer_cast<
value<double>>(shared_from_this()))
return v;
620 if(
auto v = std::dynamic_pointer_cast<
value<int64_t>>(shared_from_this()))
621 return make_value<double>(
static_cast<double>(v->get()));
628inline std::shared_ptr<const value<T>>
base::as()
const {
629#if defined(CPPTOML_NO_RTTI)
631 return std::static_pointer_cast<const value<T>>(shared_from_this());
635 return std::dynamic_pointer_cast<const value<T>>(shared_from_this());
642inline std::shared_ptr<const value<double>>
base::as()
const {
643#if defined(CPPTOML_NO_RTTI)
644 if(
type() ==
base_type::FLOAT)
return std::static_pointer_cast<const value<double>>(shared_from_this());
647 auto v = as<int64_t>();
650 return make_value<double>(
static_cast<double>(v->get()));
653 if(
auto v = std::dynamic_pointer_cast<
const value<double>>(shared_from_this()))
return v;
655 if(
auto v = as<int64_t>()) {
658 return make_value<double>(
static_cast<double>(v->get()));
677 std::shared_ptr<base>
clone()
const override;
704 std::vector<std::shared_ptr<base>>&
get() {
return values_; }
709 const std::vector<std::shared_ptr<base>>&
get()
const {
return values_; }
711 std::shared_ptr<base>
at(
size_t idx)
const {
return values_.at(idx); }
718 std::vector<std::shared_ptr<value<T>>>
array_of()
const {
719 std::vector<std::shared_ptr<value<T>>> result(
values_.size());
722 [&](
const std::shared_ptr<base>& v) { return v->as<T>(); });
733 std::vector<T> result;
734 result.reserve(
values_.size());
736 for(
const auto& val :
values_) {
737 if(
auto v = val->as<T>())
738 result.push_back(v->get());
743 return {std::move(result)};
751 std::vector<std::shared_ptr<array>> result(
values_.size());
754 [&](
const std::shared_ptr<base>& v) -> std::shared_ptr<array> {
755 if(v->is_array()) return std::static_pointer_cast<array>(v);
756 return std::shared_ptr<array>{};
767 if(values_.empty() || values_[0]->as<T>()) {
768 values_.push_back(val);
778 if(values_.empty() || values_[0]->is_array()) {
779 values_.push_back(val);
799 if(values_.empty() || values_[0]->as<T>()) {
800 return values_.insert(position,
value);
810 if(values_.empty() || values_[0]->is_array()) {
811 return values_.insert(position,
value);
822 return insert(position,
make_value(std::forward<T>(val)));
840#if not defined(MAIA_INTEL_COMPILER) and not defined(MAIA_PGI_COMPILER)
843#if defined(CPPTOML_NO_RTTI)
851 template <
class InputIterator>
852 array(InputIterator begin, InputIterator end) : values_{begin, end} {
864#if defined(MAIA_INTEL_COMPILER)
874#if not defined(MAIA_INTEL_COMPILER)
879 return std::make_shared<make_shared_enabler>();
881 return std::make_shared<ARRAY_::make_shared_enabler>();
886inline std::shared_ptr<array> make_element<array>() {
896 std::vector<std::shared_ptr<array>> result;
897 result.reserve(values_.size());
899 for(
const auto& val : values_) {
900 if(
auto v = val->as_array())
906 return {std::move(result)};
916 std::shared_ptr<base> clone()
const override;
923 using iterator = std::vector<std::shared_ptr<table>>::iterator;
940 std::vector<std::shared_ptr<table>>&
get() {
return array_; }
942 const std::vector<std::shared_ptr<table>>&
get()
const {
return array_; }
947 void push_back(
const std::shared_ptr<table>& val) { array_.push_back(val); }
969#if not defined(MAIA_INTEL_COMPILER) and not defined(MAIA_PGI_COMPILER)
972#if defined(CPPTOML_NO_RTTI)
987 std::vector<std::shared_ptr<table>>
array_;
990#if defined(MAIA_INTEL_COMPILER)
991namespace TABLE_ARRAY_ {
1000#if not defined(MAIA_INTEL_COMPILER)
1005 return std::make_shared<make_shared_enabler>();
1007 return std::make_shared<TABLE_ARRAY_::make_shared_enabler>();
1012inline std::shared_ptr<table_array> make_element<table_array>() {
1020typename std::enable_if<!std::is_floating_point<T>::value && std::is_signed<T>::value, option<T>>::type
1022 if(
auto v = elem->as<int64_t>()) {
1023 if(v->get() < std::numeric_limits<T>::min())
1024 THROW_(std::underflow_error,
"T cannot represent the value requested in get");
1026 if(v->get() > std::numeric_limits<T>::max())
1027 THROW_(std::overflow_error,
"T cannot represent the value requested in get");
1029 return {
static_cast<T
>(v->get())};
1036typename std::enable_if<!std::is_same<T, MBool>::value && std::is_unsigned<T>::value, option<T>>::type
1038 if(
auto v = elem->as<int64_t>()) {
1039 if(v->get() < 0) THROW_(std::underflow_error,
"T cannot store negative value in get");
1041 if(
static_cast<uint64_t
>(v->get()) > std::numeric_limits<T>::max())
1042 THROW_(std::overflow_error,
"T cannot represent the value requested in get");
1044 return {
static_cast<T
>(v->get())};
1051typename std::enable_if<!std::is_integral<T>::value || std::is_same<T, MBool>::value, option<T>>::type
1053 if(
auto v = elem->as<T>()) {
1068 std::shared_ptr<base> clone()
const override;
1095 MBool contains(
const std::string& key)
const {
return map_.find(key) != map_.end(); }
1108 std::shared_ptr<base>
get(
const std::string& key)
const {
return map_.at(key); }
1118 std::shared_ptr<base> p;
1119 resolve_qualified(key, &p);
1126 std::shared_ptr<table>
get_table(
const std::string& key)
const {
1127 if(contains(key) && get(key)->is_table())
return std::static_pointer_cast<table>(get(key));
1136 if(contains_qualified(key) && get_qualified(key)->is_table())
1137 return std::static_pointer_cast<table>(get_qualified(key));
1144 std::shared_ptr<array>
get_array(
const std::string& key)
const {
1145 if(!contains(key))
return nullptr;
1146 return get(key)->as_array();
1153 if(!contains_qualified(key))
return nullptr;
1154 return get_qualified(key)->as_array();
1161 if(!contains(key))
return nullptr;
1162 return get(key)->as_table_array();
1170 if(!contains_qualified(key))
return nullptr;
1171 return get_qualified(key)->as_table_array();
1180#ifndef CPPTOML_NO_EXCEPTIONS
1182 return get_impl<T>(get(key));
1183 }
catch(
const std::out_of_range&) {
1188 return get_impl<T>(get(key));
1202#ifndef CPPTOML_NO_EXCEPTIONS
1204 return get_impl<T>(get_qualified(key));
1205 }
catch(
const std::out_of_range&) {
1209 if(contains_qualified(key)) {
1210 return get_impl<T>(get_qualified(key));
1228 if(
auto v = get_array(key)) {
1229 std::vector<T> result;
1230 result.reserve(v->get().size());
1232 for(
const auto&
b : v->get()) {
1233 if(
auto val =
b->as<T>())
1234 result.push_back(val->get());
1238 return {std::move(result)};
1256 if(
auto v = get_array_qualified(key)) {
1257 std::vector<T> result;
1258 result.reserve(v->get().size());
1260 for(
const auto&
b : v->get()) {
1261 if(
auto val =
b->as<T>())
1262 result.push_back(val->get());
1266 return {std::move(result)};
1283 insert(key,
make_value(std::forward<T>(val)));
1289 void erase(
const std::string& key) { map_.erase(key); }
1291#if not defined(MAIA_INTEL_COMPILER) and not defined(MAIA_PGI_COMPILER)
1294#if defined(CPPTOML_NO_RTTI)
1309 std::vector<std::string>
split(
const std::string&
value,
char separator)
const {
1310 std::vector<std::string> result;
1311 std::string::size_type p = 0;
1312 std::string::size_type q;
1313 while((q =
value.find(separator, p)) != std::string::npos) {
1314 result.emplace_back(
value, p, q - p);
1317 result.emplace_back(
value, p);
1327 auto parts = split(key,
'.');
1328 auto last_key = parts.back();
1331 auto cur_table =
this;
1332 for(
const auto& part : parts) {
1333 cur_table = cur_table->get_table(part).get();
1335#ifndef CPPTOML_NO_EXCEPTIONS
1336 if(!p)
return false;
1338 throw std::out_of_range{key +
" is not a valid key"};
1345 if(!p)
return cur_table->map_.count(last_key) != 0;
1347 *p = cur_table->map_.at(last_key);
1365 if(
auto v = get_array(key)) {
1366 std::vector<std::shared_ptr<array>> result;
1367 result.reserve(v->get().size());
1369 for(
const auto&
b : v->get()) {
1370 if(
auto val =
b->as_array())
1371 result.push_back(val);
1376 return {std::move(result)};
1393 if(
auto v = get_array_qualified(key)) {
1394 std::vector<std::shared_ptr<array>> result;
1395 result.reserve(v->get().size());
1397 for(
const auto&
b : v->get()) {
1398 if(
auto val =
b->as_array())
1399 result.push_back(val);
1404 return {std::move(result)};
1410#if defined(MAIA_INTEL_COMPILER)
1418#if not defined(MAIA_INTEL_COMPILER)
1424 return std::make_shared<make_shared_enabler>();
1428inline std::shared_ptr<table> make_element<table>() {
1437inline std::shared_ptr<base> array::clone()
const {
1439 result->reserve(values_.size());
1440 for(
const auto& ptr : values_)
1441 result->values_.push_back(ptr->clone());
1445inline std::shared_ptr<base> table_array::clone()
const {
1447 result->reserve(array_.size());
1448 for(
const auto& ptr : array_)
1449 result->array_.push_back(ptr->clone()->as_table());
1453inline std::shared_ptr<base> table::clone()
const {
1455 for(
const auto& pr : map_)
1456 result->insert(pr.first, pr.second->clone());
1468 : std::runtime_error{err +
" at line " + std::to_string(line_number)} {}
1476template <
class OnError>
1479 consumer(std::string::iterator& it,
const std::string::iterator& end, OnError&& on_error)
1480 : it_(it), end_(end), on_error_(std::forward<OnError>(on_error)) {
1485 if(it_ == end_ || *it_ != c) on_error_();
1489 template <std::
size_t N>
1491 std::for_each(std::begin(str), std::end(str) - 1, [&](
char c) { (*this)(c); });
1496 for(
int i = 0; i < len; ++i) {
1497 if(!
is_number(*it_) || it_ == end_) on_error_();
1498 val = 10 * val + (*it_++ -
'0');
1511template <
class OnError>
1519inline std::istream&
getline(std::istream& input, std::string& line) {
1522 std::istream::sentry sentry{input,
true};
1523 auto sb = input.rdbuf();
1526 auto c = sb->sbumpc();
1528 if(sb->sgetc() ==
'\n') c = sb->sbumpc();
1531 if(c ==
'\n')
return input;
1533 if(c == std::istream::traits_type::eof()) {
1534 if(line.empty()) input.setstate(std::ios::eofbit);
1538 line.push_back(
static_cast<char>(c));
1551 explicit parser(std::istream& stream) : input_(stream) {
1566 while(detail::getline(input_, line_)) {
1568 auto it = line_.begin();
1569 auto end = line_.end();
1570 consume_whitespace(it, end);
1571 if(it == end || *it ==
'#')
continue;
1573 curr_table = root.
get();
1574 parse_table(it, end, curr_table);
1576 parse_key_value(it, end, curr_table);
1577 consume_whitespace(it, end);
1578 eol_or_comment(it, end);
1587#elif defined __GNUC__
1588 __attribute__((noreturn))
1590 void throw_parse_exception(
const std::string& err) {
1594 void parse_table(std::string::iterator& it,
const std::string::iterator& end,
table*& curr_table) {
1597 if(it == end) throw_parse_exception(
"Unexpected end of table");
1599 parse_table_array(it, end, curr_table);
1601 parse_single_table(it, end, curr_table);
1605 if(it == end || *it ==
']') throw_parse_exception(
"Table name cannot be empty");
1607 std::string full_table_name;
1608 MBool inserted =
false;
1610 auto key_end = [](
char c) {
return c ==
']'; };
1612 auto key_part_handler = [&](
const std::string& part) {
1613 if(part.empty()) throw_parse_exception(
"Empty component of table name");
1615 if(!full_table_name.empty()) full_table_name +=
'.';
1616 full_table_name += part;
1621 std::shared_ptr<base>
b = curr_table->
get(part);
1623 curr_table =
static_cast<table*
>(
b.get());
1624 else if(
b->is_table_array())
1625 curr_table = std::static_pointer_cast<table_array>(
b)->
get().back().get();
1627 throw_parse_exception(
"Key " + full_table_name +
"already exists as a value");
1631 curr_table =
static_cast<table*
>(curr_table->
get(part).get());
1635 key_part_handler(parse_key(it, end, key_end, key_part_handler));
1637 if(it == end) throw_parse_exception(
"Unterminated table declaration; did you forget a ']'?");
1640 std::string errmsg{
"Unexpected character in table definition: "};
1644 throw_parse_exception(errmsg);
1649 auto is_value = [](
const std::pair<const std::string&, const std::shared_ptr<base>&>& p) {
1650 return p.second->is_value();
1657 if(curr_table->
empty() || std::any_of(curr_table->
begin(), curr_table->
end(), is_value)) {
1658 throw_parse_exception(
"Redefinition of table " + full_table_name);
1663 consume_whitespace(it, end);
1664 eol_or_comment(it, end);
1669 if(it == end || *it ==
']') throw_parse_exception(
"Table array name cannot be empty");
1671 auto key_end = [](
char c) {
return c ==
']'; };
1674 std::string full_ta_name;
1675 auto key_part_handler = [&](
const std::string& part) {
1676 if(part.empty()) throw_parse_exception(
"Empty component of table array name");
1678 if(!full_ta_name.empty()) full_ta_name +=
'.';
1679 full_ta_name += part;
1684 std::shared_ptr<base>
b = curr_table->
get(part);
1688 if(it != end && *it ==
']') {
1689 if(!
b->is_table_array()) throw_parse_exception(
"Key " + full_ta_name +
" is not a table array");
1690 auto v =
b->as_table_array();
1692 curr_table = v->
get().back().get();
1697 curr_table =
static_cast<table*
>(
b.get());
1698 else if(
b->is_table_array())
1699 curr_table = std::static_pointer_cast<table_array>(
b)->
get().back().get();
1701 throw_parse_exception(
"Key " + full_ta_name +
" already exists as a value");
1707 if(it != end && *it ==
']') {
1709 auto arr = std::static_pointer_cast<table_array>(curr_table->
get(part));
1711 curr_table = arr->
get().back().get();
1717 curr_table =
static_cast<table*
>(curr_table->
get(part).get());
1722 key_part_handler(parse_key(it, end, key_end, key_part_handler));
1725 auto eat =
make_consumer(it, end, [
this]() { throw_parse_exception(
"Unterminated table array name"); });
1729 consume_whitespace(it, end);
1730 eol_or_comment(it, end);
1734 auto key_end = [](
char c) {
return c ==
'='; };
1736 auto key_part_handler = [&](
const std::string& part) {
1741 auto val = curr_table->
get(part);
1742 if(val->is_table()) {
1743 curr_table =
static_cast<table*
>(val.get());
1745 throw_parse_exception(
"Key " + part +
" already exists as a value");
1749 curr_table->
insert(part, newtable);
1750 curr_table = newtable.
get();
1754 auto key = parse_key(it, end, key_end, key_part_handler);
1756 if(curr_table->
contains(key)) throw_parse_exception(
"Key " + key +
" already present");
1757 if(it == end || *it !=
'=') throw_parse_exception(
"Value must follow after a '='");
1759 consume_whitespace(it, end);
1760 curr_table->
insert(key, parse_value(it, end));
1761 consume_whitespace(it, end);
1764 template <
class KeyEndFinder,
class KeyPartHandler>
1765 std::string
parse_key(std::string::iterator& it,
const std::string::iterator& end, KeyEndFinder&& key_end,
1766 KeyPartHandler&& key_part_handler) {
1768 while(it != end && !key_end(*it)) {
1769 auto part = parse_simple_key(it, end);
1770 consume_whitespace(it, end);
1772 if(it == end || key_end(*it)) {
1777 std::string errmsg{
"Unexpected character in key: "};
1781 throw_parse_exception(errmsg);
1784 key_part_handler(part);
1790 throw_parse_exception(
"Unexpected end of key");
1794 consume_whitespace(it, end);
1797 if(it == end) throw_parse_exception(
"Unexpected end of key (blank key?)");
1799 if(*it ==
'"' || *it ==
'\'') {
1800 return string_literal(it, end, *it);
1802 auto bke = std::find_if(it, end, [](
char c) {
return c ==
'.' || c ==
'=' || c ==
']'; });
1803 return parse_bare_key(it, bke);
1808 std::string
parse_bare_key(std::string::iterator& it,
const std::string::iterator& end) {
1810 throw_parse_exception(
"Bare key missing name");
1815 consume_backwards_whitespace(key_end, it);
1817 std::string key{it, key_end};
1819 if(std::find(it, key_end,
'#') != key_end) {
1820 throw_parse_exception(
"Bare key " + key +
" cannot contain #");
1823 if(std::find_if(it, key_end, [](
char c) {
return c ==
' ' || c ==
'\t'; }) != key_end) {
1824 throw_parse_exception(
"Bare key " + key +
" cannot contain whitespace");
1827 if(std::find_if(it, key_end, [](
char c) {
return c ==
'[' || c ==
']'; }) != key_end) {
1828 throw_parse_exception(
"Bare key " + key +
" cannot contain '[' or ']'");
1848 std::shared_ptr<base>
parse_value(std::string::iterator& it, std::string::iterator& end) {
1849 parse_type type = determine_value_type(it, end);
1851 case parse_type::STRING:
1852 return parse_string(it, end);
1853 case parse_type::LOCAL_TIME:
1854 return parse_time(it, end);
1855 case parse_type::LOCAL_DATE:
1856 case parse_type::LOCAL_DATETIME:
1857 case parse_type::OFFSET_DATETIME:
1858 return parse_date(it, end);
1859 case parse_type::INT:
1860 case parse_type::FLOAT:
1861 return parse_number(it, end);
1862 case parse_type::BOOL:
1863 return parse_bool(it, end);
1864 case parse_type::ARRAY:
1865 return parse_array(it, end);
1866 case parse_type::INLINE_TABLE:
1867 return parse_inline_table(it, end);
1869 throw_parse_exception(
"Failed to parse value");
1875 throw_parse_exception(
"Failed to parse value type");
1877 if(*it ==
'"' || *it ==
'\'') {
1878 return parse_type::STRING;
1879 }
else if(is_time(it, end)) {
1880 return parse_type::LOCAL_TIME;
1881 }
else if(
auto dtype = date_type(it, end)) {
1883 }
else if(
is_number(*it) || *it ==
'-' || *it ==
'+') {
1884 return determine_number_type(it, end);
1885 }
else if(*it ==
't' || *it ==
'f') {
1886 return parse_type::BOOL;
1887 }
else if(*it ==
'[') {
1888 return parse_type::ARRAY;
1889 }
else if(*it ==
'{') {
1890 return parse_type::INLINE_TABLE;
1892 throw_parse_exception(
"Failed to parse value type");
1898 if(*check_it ==
'-' || *check_it ==
'+') ++check_it;
1899 while(check_it != end &&
is_number(*check_it))
1901 if(check_it != end && *check_it ==
'.') {
1903 while(check_it != end &&
is_number(*check_it))
1905 return parse_type::FLOAT;
1907 return parse_type::INT;
1911 std::shared_ptr<value<std::string>>
parse_string(std::string::iterator& it, std::string::iterator& end) {
1913 assert(delim ==
'"' || delim ==
'\'');
1919 if(check_it != end && *check_it == delim) {
1921 if(check_it != end && *check_it == delim) {
1923 return parse_multiline_string(it, end, delim);
1926 return make_value<std::string>(string_literal(it, end, delim));
1931 std::stringstream ss;
1933 auto is_ws = [](
char c) {
return c ==
' ' || c ==
'\t'; };
1935 MBool consuming =
false;
1936 std::shared_ptr<value<std::string>> ret;
1938 auto handle_line = [&](std::string::iterator& local_it, std::string::iterator& local_end) {
1940 local_it = std::find_if_not(local_it, local_end, is_ws);
1943 if(local_it == local_end)
return;
1948 while(local_it != local_end) {
1950 if(delim ==
'"' && *local_it ==
'\\') {
1951 auto check = local_it;
1955 consume_whitespace(check, local_end);
1956 if(check == local_end) {
1961 ss << parse_escape_code(local_it, local_end);
1966 if(std::distance(local_it, local_end) >= 3) {
1967 auto check = local_it;
1969 if(*check++ == delim && *check++ == delim && *check++ == delim) {
1971 ret = make_value<std::string>(ss.str());
1981 handle_line(it, end);
1985 while(detail::getline(input_, line_)) {
1991 handle_line(it, end);
1995 if(!consuming) ss << std::endl;
1998 throw_parse_exception(
"Unterminated multi-line basic string");
2001 std::string
string_literal(std::string::iterator& it,
const std::string::iterator& end,
char delim) {
2006 if(delim ==
'"' && *it ==
'\\') {
2007 val += parse_escape_code(it, end);
2008 }
else if(*it == delim) {
2010 consume_whitespace(it, end);
2016 throw_parse_exception(
"Unterminated string literal");
2021 if(it == end) throw_parse_exception(
"Invalid escape sequence");
2025 }
else if(*it ==
't') {
2027 }
else if(*it ==
'n') {
2029 }
else if(*it ==
'f') {
2031 }
else if(*it ==
'r') {
2033 }
else if(*it ==
'"') {
2035 }
else if(*it ==
'\\') {
2037 }
else if(*it ==
'u' || *it ==
'U') {
2038 return parse_unicode(it, end);
2040 throw_parse_exception(
"Invalid escape sequence");
2043 return std::string(1,
value);
2046 std::string
parse_unicode(std::string::iterator& it,
const std::string::iterator& end) {
2047 MBool large = *it++ ==
'U';
2048 auto codepoint = parse_hex(it, end, large ? 0x10000000 : 0x1000);
2050 if((codepoint > 0xd7ff && codepoint < 0xe000) || codepoint > 0x10ffff) {
2051 throw_parse_exception(
"Unicode escape sequence is not a Unicode scalar value");
2056 if(codepoint <= 0x7f) {
2059 result +=
static_cast<char>(codepoint & 0x7f);
2060 }
else if(codepoint <= 0x7ff) {
2067 result +=
static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f));
2072 result +=
static_cast<char>(0x80 | (codepoint & 0x3f));
2073 }
else if(codepoint <= 0xffff) {
2080 result +=
static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f));
2081 result +=
static_cast<char>(0x80 | ((codepoint >> 6) & 0x1f));
2082 result +=
static_cast<char>(0x80 | (codepoint & 0x3f));
2090 result +=
static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07));
2091 result +=
static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f));
2092 result +=
static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f));
2093 result +=
static_cast<char>(0x80 | (codepoint & 0x3f));
2098 uint32_t
parse_hex(std::string::iterator& it,
const std::string::iterator& end, uint32_t place) {
2101 if(it == end) throw_parse_exception(
"Unexpected end of unicode sequence");
2103 if(!is_hex(*it)) throw_parse_exception(
"Invalid unicode escape sequence");
2105 value += place * hex_to_digit(*it++);
2114 if(
is_number(c))
return static_cast<uint32_t
>(c -
'0');
2115 return 10 +
static_cast<uint32_t
>(c - ((c >=
'a' && c <=
'f') ?
'a' :
'A'));
2118 std::shared_ptr<base>
parse_number(std::string::iterator& it,
const std::string::iterator& end) {
2120 auto check_end = find_end_of_number(it, end);
2122 auto eat_sign = [&]() {
2123 if(check_it != end && (*check_it ==
'-' || *check_it ==
'+')) ++check_it;
2128 auto eat_numbers = [&]() {
2129 auto beg = check_it;
2130 while(check_it != end &&
is_number(*check_it)) {
2132 if(check_it != end && *check_it ==
'_') {
2134 if(check_it == end || !
is_number(*check_it)) throw_parse_exception(
"Malformed number");
2138 if(check_it == beg) throw_parse_exception(
"Malformed number");
2141 auto check_no_leading_zero = [&]() {
2142 if(check_it != end && *check_it ==
'0' && check_it + 1 != check_end && check_it[1] !=
'.') {
2143 throw_parse_exception(
"Numbers may not have leading zeros");
2147 check_no_leading_zero();
2150 if(check_it != end && (*check_it ==
'.' || *check_it ==
'e' || *check_it ==
'E')) {
2151 MBool is_exp = *check_it ==
'e' || *check_it ==
'E';
2154 if(check_it == end) throw_parse_exception(
"Floats must have trailing digits");
2156 auto eat_exp = [&]() {
2158 check_no_leading_zero();
2167 if(!is_exp && check_it != end && (*check_it ==
'e' || *check_it ==
'E')) {
2172 return parse_float(it, check_it);
2174 return parse_int(it, check_it);
2178 std::shared_ptr<value<int64_t>>
parse_int(std::string::iterator& it,
const std::string::iterator& end) {
2179 std::string v{it, end};
2180 v.erase(std::remove(v.begin(), v.end(),
'_'), v.end());
2182#ifndef CPPTOML_NO_EXCEPTIONS
2186 return make_value<int64_t>(std::stoll(v));
2188#ifndef CPPTOML_NO_EXCEPTIONS
2189 catch(
const std::invalid_argument& ex) {
2190 throw_parse_exception(
"Malformed number (invalid argument: " + std::string{ex.what()} +
")");
2191 }
catch(
const std::out_of_range& ex) {
2192 throw_parse_exception(
"Malformed number (out of range: " + std::string{ex.what()} +
")");
2197 std::shared_ptr<value<double>>
parse_float(std::string::iterator& it,
const std::string::iterator& end) {
2198 std::string v{it, end};
2199 v.erase(std::remove(v.begin(), v.end(),
'_'), v.end());
2201 char decimal_point = std::localeconv()->decimal_point[0];
2202 std::replace(v.begin(), v.end(),
'.', decimal_point);
2203#ifndef CPPTOML_NO_EXCEPTIONS
2207 return make_value<double>(std::stod(v));
2209#ifndef CPPTOML_NO_EXCEPTIONS
2210 catch(
const std::invalid_argument& ex) {
2211 throw_parse_exception(
"Malformed number (invalid argument: " + std::string{ex.what()} +
")");
2212 }
catch(
const std::out_of_range& ex) {
2213 throw_parse_exception(
"Malformed number (out of range: " + std::string{ex.what()} +
")");
2218 std::shared_ptr<value<MBool>>
parse_bool(std::string::iterator& it,
const std::string::iterator& end) {
2219 auto eat =
make_consumer(it, end, [
this]() { throw_parse_exception(
"Attempted to parse invalid boolean value"); });
2223 return make_value<MBool>(
true);
2224 }
else if(*it ==
'f') {
2226 return make_value<MBool>(
false);
2234 return std::find_if(it, end, [](
char c) {
2235 return !
is_number(c) && c !=
'_' && c !=
'.' && c !=
'e' && c !=
'E' && c !=
'-' && c !=
'+';
2239 static std::string::iterator
find_end_of_date(std::string::iterator it, std::string::iterator end) {
2240 return std::find_if(it, end, [](
char c) {
2241 return !
is_number(c) && c !=
'T' && c !=
'Z' && c !=
':' && c !=
'-' && c !=
'+' && c !=
'.';
2245 static std::string::iterator
find_end_of_time(std::string::iterator it, std::string::iterator end) {
2246 return std::find_if(it, end, [](
char c) {
return !
is_number(c) && c !=
':' && c !=
'.'; });
2250 auto time_end = find_end_of_time(it, end);
2252 auto eat =
make_consumer(it, time_end, [&]() { throw_parse_exception(
"Malformed time"); });
2256 ltime.
hour = eat.eat_digits(2);
2258 ltime.minute = eat.eat_digits(2);
2260 ltime.second = eat.eat_digits(2);
2263 if(it != time_end && *it ==
'.') {
2265 while(it != time_end &&
is_number(*it)) {
2266 ltime.microsecond += power * (*it++ -
'0');
2271 if(it != time_end) throw_parse_exception(
"Malformed time");
2276 std::shared_ptr<value<local_time>>
parse_time(std::string::iterator& it,
const std::string::iterator& end) {
2280 std::shared_ptr<base>
parse_date(std::string::iterator& it,
const std::string::iterator& end) {
2281 auto date_end = find_end_of_date(it, end);
2283 auto eat =
make_consumer(it, date_end, [&]() { throw_parse_exception(
"Malformed date"); });
2286 ldate.
year = eat.eat_digits(4);
2288 ldate.month = eat.eat_digits(2);
2290 ldate.day = eat.eat_digits(2);
2298 static_cast<local_time&
>(ldt) = read_time(it, date_end);
2307 if(*it ==
'+' || *it ==
'-') {
2308 auto plus = *it ==
'+';
2311 hoff = eat.eat_digits(2);
2314 moff = eat.eat_digits(2);
2316 }
else if(*it ==
'Z') {
2320 if(it != date_end) throw_parse_exception(
"Malformed date");
2325 std::shared_ptr<base>
parse_array(std::string::iterator& it, std::string::iterator& end) {
2335 skip_whitespace_and_comments(it, end);
2343 auto val_end = std::find_if(it, end, [](
char c) {
return c ==
',' || c ==
']' || c ==
'#'; });
2344 parse_type type = determine_value_type(it, val_end);
2346 case parse_type::STRING:
2347 return parse_value_array<std::string>(it, end);
2348 case parse_type::LOCAL_TIME:
2349 return parse_value_array<local_time>(it, end);
2350 case parse_type::LOCAL_DATE:
2351 return parse_value_array<local_date>(it, end);
2352 case parse_type::LOCAL_DATETIME:
2353 return parse_value_array<local_datetime>(it, end);
2354 case parse_type::OFFSET_DATETIME:
2355 return parse_value_array<offset_datetime>(it, end);
2356 case parse_type::INT:
2357 return parse_value_array<int64_t>(it, end);
2358 case parse_type::FLOAT:
2359 return parse_value_array<double>(it, end);
2360 case parse_type::BOOL:
2361 return parse_value_array<MBool>(it, end);
2362 case parse_type::ARRAY:
2363 return parse_object_array<array>(&parser::parse_array,
'[', it, end);
2364 case parse_type::INLINE_TABLE:
2365 return parse_object_array<table_array>(&parser::parse_inline_table,
'{', it, end);
2367 throw_parse_exception(
"Unable to parse array");
2371 template <
class Value>
2374 while(it != end && *it !=
']') {
2375 auto val = parse_value(it, end);
2376 if(
auto v = val->as<Value>())
2377 arr->get().push_back(val);
2379 throw_parse_exception(
"Arrays must be homogeneous");
2380 skip_whitespace_and_comments(it, end);
2381 if(*it !=
',')
break;
2383 skip_whitespace_and_comments(it, end);
2389 template <
class Object,
class Function>
2391 std::string::iterator& end) {
2392 auto arr = make_element<Object>();
2394 while(it != end && *it !=
']') {
2395 if(*it != delim) throw_parse_exception(
"Unexpected character in array");
2397 arr->get().push_back(((*this).*fun)(it, end));
2398 skip_whitespace_and_comments(it, end);
2400 if(*it !=
',')
break;
2403 skip_whitespace_and_comments(it, end);
2406 if(it == end || *it !=
']') throw_parse_exception(
"Unterminated array");
2416 if(it == end) throw_parse_exception(
"Unterminated inline table");
2418 consume_whitespace(it, end);
2419 parse_key_value(it, end, tbl.get());
2420 consume_whitespace(it, end);
2421 }
while(*it ==
',');
2423 if(it == end || *it !=
'}') throw_parse_exception(
"Unterminated inline table");
2426 consume_whitespace(it, end);
2432 consume_whitespace(start, end);
2433 while(start == end || *start ==
'#') {
2434 if(!detail::getline(input_, line_)) throw_parse_exception(
"Unclosed array");
2436 start = line_.begin();
2438 consume_whitespace(start, end);
2443 while(it != end && (*it ==
' ' || *it ==
'\t'))
2448 while(back != front && (*back ==
' ' || *back ==
'\t'))
2452 void eol_or_comment(
const std::string::iterator& it,
const std::string::iterator& end) {
2453 if(it != end && *it !=
'#')
2454 throw_parse_exception(
"Unidentified trailing character '" + std::string{*it} +
"'---did you forget a '#'?");
2457 static MBool is_time(
const std::string::iterator& it,
const std::string::iterator& end) {
2458 auto time_end = find_end_of_time(it, end);
2459 auto len = std::distance(it, time_end);
2461 if(len < 8)
return false;
2463 if(it[2] !=
':' || it[5] !=
':')
return false;
2465 if(len > 8)
return it[8] ==
'.' && len > 9;
2471 auto date_end = find_end_of_date(it, end);
2472 auto len = std::distance(it, date_end);
2474 if(len < 10)
return {};
2476 if(it[4] !=
'-' || it[7] !=
'-')
return {};
2478 if(len >= 19 && it[10] ==
'T' && is_time(it + 11, date_end)) {
2480 auto time_end = find_end_of_time(it + 11, date_end);
2481 if(time_end == date_end)
2482 return {parse_type::LOCAL_DATETIME};
2484 return {parse_type::OFFSET_DATETIME};
2485 }
else if(len == 10) {
2487 return {parse_type::LOCAL_DATE};
2495 std::size_t line_number_ = 0;
2502inline std::shared_ptr<table>
parse_file(
const std::string& filename) {
2503#if defined(BOOST_NOWIDE_FSTREAM_INCLUDED_HPP)
2504 boost::nowide::ifstream file{filename.c_str()};
2505#elif defined(NOWIDE_FSTREAM_INCLUDED_HPP)
2506 nowide::ifstream file{filename.c_str()};
2508 std::ifstream file{filename};
2510 if(!file.is_open()) THROW_(
parse_exception, filename +
" could not be opened for parsing");
2515template <
class... Ts>
2520 template <
class Visitor,
class... Args>
2526template <
class T,
class... Ts>
2528 template <
class Visitor,
class... Args>
2529 static void accept(
const base&
b, Visitor&& visitor, Args&&... args) {
2530 if(
auto v =
b.as<T>()) {
2531 visitor.visit(*v, std::forward<Args>(args)...);
2542template <
class Visitor,
class... Args>
2543void base::accept(Visitor&& visitor, Args&&... args)
const {
2544#if defined(MAIA_GCC_COMPILER)
2545#pragma GCC diagnostic push
2546#pragma GCC diagnostic ignored "-Wnull-dereference"
2550 using value_acceptor =
2552 value_acceptor::accept(*
this, std::forward<Visitor>(visitor), std::forward<Args>(args)...);
2553 }
else if(is_table()) {
2554 visitor.visit(
static_cast<const table&
>(*
this), std::forward<Args>(args)...);
2555 }
else if(is_array()) {
2556 visitor.visit(
static_cast<const array&
>(*
this), std::forward<Args>(args)...);
2557 }
else if(is_table_array()) {
2558 visitor.visit(
static_cast<const table_array&
>(*
this), std::forward<Args>(args)...);
2560#if defined(MAIA_GCC_COMPILER)
2561#pragma GCC diagnostic pop
2574 explicit toml_writer(std::ostream& s, std::string indent_space =
"\t")
2575 : stream_(s), indent_(std::move(indent_space)), has_naked_endline_(false) {
2592 write_table_header(in_array);
2593 std::vector<std::string> values;
2594 std::vector<std::string> tables;
2596 for(
const auto& i : t) {
2597 if(i.second->is_table() || i.second->is_table_array()) {
2598 tables.push_back(i.first);
2600 values.push_back(i.first);
2604 for(
MUint i = 0; i < values.size(); ++i) {
2605 path_.push_back(values[i]);
2607 if(i > 0) endline();
2609 write_table_item_header(*t.
get(values[i]));
2610 t.
get(values[i])->accept(*
this,
false);
2614 for(
MUint i = 0; i < tables.size(); ++i) {
2615 path_.push_back(tables[i]);
2617 if(!values.empty() || i > 0) endline();
2619 write_table_item_header(*t.
get(tables[i]));
2620 t.
get(tables[i])->accept(*
this,
false);
2633 for(
MUint i = 0; i <
a.get().size(); ++i) {
2634 if(i > 0) write(
", ");
2636 if(
a.get()[i]->is_array()) {
2637 a.get()[i]->as_array()->accept(*
this,
true);
2639 a.get()[i]->accept(*
this,
true);
2650 for(
MUint j = 0; j < t.
get().size(); ++j) {
2651 if(j > 0) endline();
2653 t.
get()[j]->accept(*
this,
true);
2664 for(
char it : str) {
2667 }
else if(it ==
'\t') {
2669 }
else if(it ==
'\n') {
2671 }
else if(it ==
'\f') {
2673 }
else if(it ==
'\r') {
2675 }
else if(it ==
'"') {
2677 }
else if(it ==
'\\') {
2679 }
else if((uint32_t)it <= 0x001f) {
2681 std::stringstream ss;
2682 ss << std::hex << static_cast<uint32_t>(it);
2697 write(escape_string(v.
get()));
2705 std::ios::fmtflags flags{stream_.flags()};
2707 stream_ << std::showpoint;
2710 stream_.flags(flags);
2718 typename std::enable_if<is_one_of<T, int64_t, local_date, local_time, local_datetime, offset_datetime>::value>::type
2732 if(!path_.empty()) {
2741 for(
MUint i = 0; i < path_.size(); ++i) {
2746 if(path_[i].find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"
2747 "fghijklmnopqrstuvwxyz0123456789"
2749 == std::string::npos) {
2753 write(escape_string(path_[i]));
2771 if(!
b.is_table() && !
b.is_table_array()) {
2774 if(path_.back().find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"
2775 "fghijklmnopqrstuvwxyz0123456789"
2777 == std::string::npos) {
2778 write(path_.back());
2781 write(escape_string(path_.back()));
2795 for(std::size_t i = 1; i < path_.size(); ++i)
2805 has_naked_endline_ =
false;
2812 if(!has_naked_endline_) {
2814 has_naked_endline_ =
true;
2857#if defined(CPPTOML_NO_EXCEPTIONS)
make_shared_enabler()=default
make_shared_enabler()=default
array_exception(const std::string &err)
std::vector< std::shared_ptr< base > > values_
const std::vector< std::shared_ptr< base > > & get() const
const_iterator begin() const
array(const array &obj)=delete
array & operator=(const array &obj)=delete
iterator insert(iterator position, const std::shared_ptr< array > &value)
std::shared_ptr< base > at(size_t idx) const
std::vector< std::shared_ptr< array > > nested_array() const
void reserve(size_type n)
array_of_trait< T >::return_type get_array_of() const
iterator insert(iterator position, const std::shared_ptr< value< T > > &value)
iterator erase(iterator position)
std::vector< std::shared_ptr< value< T > > > array_of() const
void push_back(const std::shared_ptr< value< T > > &val)
const_iterator end() const
friend std::shared_ptr< array > make_array()
MBool is_array() const override
iterator insert(iterator position, T &&val, typename value_traits< T >::type *=0)
void push_back(T &&val, typename value_traits< T >::type *=0)
std::vector< std::shared_ptr< base > >::const_iterator const_iterator
void push_back(const std::shared_ptr< array > &val)
array(InputIterator begin, InputIterator end)
std::shared_ptr< base > clone() const override
std::vector< std::shared_ptr< base > >::iterator iterator
std::vector< std::shared_ptr< base > > & get()
virtual MBool is_array() const
std::shared_ptr< table > as_table()
virtual MBool is_table_array() const
virtual std::shared_ptr< base > clone() const =0
virtual MBool is_table() const
virtual MBool is_value() const
void accept(Visitor &&visitor, Args &&... args) const
std::shared_ptr< table_array > as_table_array()
std::shared_ptr< value< T > > as()
std::shared_ptr< array > as_array()
std::string::iterator & it_
void operator()(const char(&str)[N])
consumer(std::string::iterator &it, const std::string::iterator &end, OnError &&on_error)
const std::string::iterator & end_
std::ostream::char_type fill_
fill_guard(std::ostream &os)
make_shared_enabler()=default
const T * operator->() const
const T & operator*() const
const T & value_or(const T &alternative) const
parse_exception(const std::string &err, std::size_t line_number)
parse_exception(const std::string &err)
parser & operator=(const parser &parser)=delete
std::shared_ptr< value< local_time > > parse_time(std::string::iterator &it, const std::string::iterator &end)
std::shared_ptr< base > parse_array(std::string::iterator &it, std::string::iterator &end)
std::shared_ptr< base > parse_date(std::string::iterator &it, const std::string::iterator &end)
std::shared_ptr< table > parse_inline_table(std::string::iterator &it, std::string::iterator &end)
std::string parse_bare_key(std::string::iterator &it, const std::string::iterator &end)
void parse_single_table(std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
std::shared_ptr< value< std::string > > parse_multiline_string(std::string::iterator &it, std::string::iterator &end, char delim)
static option< parse_type > date_type(const std::string::iterator &it, const std::string::iterator &end)
static std::string::iterator find_end_of_date(std::string::iterator it, std::string::iterator end)
void parse_key_value(std::string::iterator &it, std::string::iterator &end, table *curr_table)
static void consume_backwards_whitespace(std::string::iterator &back, const std::string::iterator &front)
static void consume_whitespace(std::string::iterator &it, const std::string::iterator &end)
std::string parse_simple_key(std::string::iterator &it, const std::string::iterator &end)
std::string parse_unicode(std::string::iterator &it, const std::string::iterator &end)
std::shared_ptr< table > parse()
void parse_table(std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
uint32_t parse_hex(std::string::iterator &it, const std::string::iterator &end, uint32_t place)
std::shared_ptr< value< double > > parse_float(std::string::iterator &it, const std::string::iterator &end)
void eol_or_comment(const std::string::iterator &it, const std::string::iterator &end)
static parse_type determine_number_type(const std::string::iterator &it, const std::string::iterator &end)
parser(std::istream &stream)
std::string parse_escape_code(std::string::iterator &it, const std::string::iterator &end)
std::shared_ptr< base > parse_value(std::string::iterator &it, std::string::iterator &end)
std::shared_ptr< Object > parse_object_array(Function &&fun, char delim, std::string::iterator &it, std::string::iterator &end)
static MBool is_hex(char c)
void parse_table_array(std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
std::string string_literal(std::string::iterator &it, const std::string::iterator &end, char delim)
std::string parse_key(std::string::iterator &it, const std::string::iterator &end, KeyEndFinder &&key_end, KeyPartHandler &&key_part_handler)
static uint32_t hex_to_digit(char c)
static std::string::iterator find_end_of_number(std::string::iterator it, std::string::iterator end)
local_time read_time(std::string::iterator &it, const std::string::iterator &end)
void skip_whitespace_and_comments(std::string::iterator &start, std::string::iterator &end)
std::shared_ptr< array > parse_value_array(std::string::iterator &it, std::string::iterator &end)
static std::string::iterator find_end_of_time(std::string::iterator it, std::string::iterator end)
parse_type determine_value_type(const std::string::iterator &it, const std::string::iterator &end)
std::shared_ptr< value< std::string > > parse_string(std::string::iterator &it, std::string::iterator &end)
std::shared_ptr< base > parse_number(std::string::iterator &it, const std::string::iterator &end)
__declspec(noreturn) __attribute__((noreturn)) void throw_parse_exception(const std
static MBool is_time(const std::string::iterator &it, const std::string::iterator &end)
std::shared_ptr< value< int64_t > > parse_int(std::string::iterator &it, const std::string::iterator &end)
std::shared_ptr< value< MBool > > parse_bool(std::string::iterator &it, const std::string::iterator &end)
MBool is_table_array() const override
table_array & operator=(const table_array &rhs)=delete
const_iterator begin() const
const std::vector< std::shared_ptr< table > > & get() const
std::vector< std::shared_ptr< table > >::iterator iterator
void push_back(const std::shared_ptr< table > &val)
iterator erase(iterator position)
void reserve(size_type n)
table_array(const table_array &obj)=delete
iterator insert(iterator position, const std::shared_ptr< table > &value)
std::vector< std::shared_ptr< table > > array_
std::vector< std::shared_ptr< table > >::const_iterator const_iterator
const_iterator end() const
std::vector< std::shared_ptr< table > > & get()
std::shared_ptr< base > get(const std::string &key) const
void insert(const std::string &key, T &&val, typename value_traits< T >::type *=0)
std::shared_ptr< table > get_table(const std::string &key) const
option< T > get_qualified_as(const std::string &key) const
const_iterator begin() const
string_to_base_map::iterator iterator
array_of_trait< T >::return_type get_array_of(const std::string &key) const
void insert(const std::string &key, const std::shared_ptr< base > &value)
std::shared_ptr< base > get_qualified(const std::string &key) const
MBool is_table() const override
option< T > get_as(const std::string &key) const
void erase(const std::string &key)
MBool contains(const std::string &key) const
table & operator=(const table &rhs)=delete
string_to_base_map::const_iterator const_iterator
std::shared_ptr< array > get_array(const std::string &key) const
std::shared_ptr< table_array > get_table_array(const std::string &key) const
std::shared_ptr< table > get_table_qualified(const std::string &key) const
const_iterator end() const
MBool contains_qualified(const std::string &key) const
std::shared_ptr< array > get_array_qualified(const std::string &key) const
std::vector< std::string > split(const std::string &value, char separator) const
std::shared_ptr< table_array > get_table_array_qualified(const std::string &key) const
MBool resolve_qualified(const std::string &key, std::shared_ptr< base > *p=nullptr) const
array_of_trait< T >::return_type get_qualified_array_of(const std::string &key) const
table(const table &obj)=delete
std::vector< std::string > path_
void write_table_item_header(const base &b)
toml_writer(std::ostream &s, std::string indent_space="\t")
std::enable_if< is_one_of< T, int64_t, local_date, local_time, local_datetime, offset_datetime >::value >::type write(const value< T > &v)
void write_table_header(MBool in_array=false)
void visit(const table &t, MBool in_array=false)
const std::string indent_
void visit(const table_array &t, MBool=false)
void write(const value< MBool > &v)
void write(const value< double > &v)
static std::string escape_string(const std::string &str)
void write(const value< std::string > &v)
void visit(const value< T > &v, MBool=false)
void visit(const array &a, MBool=false)
MBool is_value() const override
value & operator=(const value &val)=delete
std::shared_ptr< base > clone() const override
value(const make_shared_enabler &, const T &val)
value(const value &val)=delete
constexpr std::array< T, n > make_array(const T v)
std::ostream & operator<<(std::ostream &os, const LPTEllipsoidal< nDim > &m)
std::istream & getline(std::istream &input, std::string &line)
std::shared_ptr< table > make_table()
std::map< std::string, std::shared_ptr< base > > string_to_base_map
std::shared_ptr< table > parse_file(const std::string &filename)
void die(const std::string &reason, const std::string &file, const int line)
std::shared_ptr< T > make_element()
CPPTOML_DEPRECATED("datetime has been renamed to offset_datetime") typedef offset_datetime datetime
std::ostream & operator<<(std::ostream &os, const local_date &dt)
std::shared_ptr< table_array > make_table_array()
consumer< OnError > make_consumer(std::string::iterator &it, const std::string::iterator &end, OnError &&on_error)
std::shared_ptr< typename value_traits< T >::type > make_value(T &&val)
std::shared_ptr< array > make_array()
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)
base_type
Base type used to store underlying data type explicitly if RTTI is disabled.
Type traits class to convert C++ types to enum member.
static offset_datetime from_zoned(const tm &t)
static offset_datetime from_utc(const tm &t)
CPPTOML_DEPRECATED("from_local has been renamed to from_zoned") static inline offset_datetime from_local(const tm &t)
static void accept(const base &b, Visitor &&visitor, Args &&... args)
static void accept(const base &, Visitor &&, Args &&...)
typename std::conditional< valid_value< typename std::decay< T >::type >::value, typename std::decay< T >::type, std::string >::type value_type
static value_type construct(T &&val)
static value_type construct(T &&val)
static value_type construct(T &&val)
typename std::decay< T >::type value_type
static value_type construct(T &&val)