318
+ − 1 // Copyright Toru Niina 2017.
+ − 2 // Distributed under the MIT License.
+ − 3 #ifndef TOML11_VALUE_HPP
+ − 4 #define TOML11_VALUE_HPP
+ − 5 #include <cassert>
+ − 6
+ − 7 #include "comments.hpp"
+ − 8 #include "exception.hpp"
+ − 9 #include "into.hpp"
+ − 10 #include "region.hpp"
+ − 11 #include "source_location.hpp"
+ − 12 #include "storage.hpp"
+ − 13 #include "traits.hpp"
+ − 14 #include "types.hpp"
+ − 15 #include "utility.hpp"
+ − 16
+ − 17 namespace toml
+ − 18 {
+ − 19
+ − 20 namespace detail
+ − 21 {
+ − 22
+ − 23 // to show error messages. not recommended for users.
+ − 24 template<typename Value>
+ − 25 inline region_base const* get_region(const Value& v)
+ − 26 {
+ − 27 return v.region_info_.get();
+ − 28 }
+ − 29
+ − 30 template<typename Value>
+ − 31 void change_region(Value& v, region reg)
+ − 32 {
+ − 33 v.region_info_ = std::make_shared<region>(std::move(reg));
+ − 34 return;
+ − 35 }
+ − 36
+ − 37 template<value_t Expected, typename Value>
+ − 38 [[noreturn]] inline void
+ − 39 throw_bad_cast(const std::string& funcname, value_t actual, const Value& v)
+ − 40 {
+ − 41 throw type_error(detail::format_underline(
+ − 42 concat_to_string(funcname, "bad_cast to ", Expected), {
+ − 43 {v.location(), concat_to_string("the actual type is ", actual)}
+ − 44 }), v.location());
+ − 45 }
+ − 46
+ − 47 // Throw `out_of_range` from `toml::value::at()` and `toml::find()`
+ − 48 // after generating an error message.
+ − 49 //
+ − 50 // The implementation is a bit complicated and there are many edge-cases.
+ − 51 // If you are not interested in the error message generation, just skip this.
+ − 52 template<typename Value>
+ − 53 [[noreturn]] void
+ − 54 throw_key_not_found_error(const Value& v, const key& ky)
+ − 55 {
+ − 56 // The top-level table has its region at the first character of the file.
+ − 57 // That means that, in the case when a key is not found in the top-level
+ − 58 // table, the error message points to the first character. If the file has
+ − 59 // its first table at the first line, the error message would be like this.
+ − 60 // ```console
+ − 61 // [error] key "a" not found
+ − 62 // --> example.toml
+ − 63 // |
+ − 64 // 1 | [table]
+ − 65 // | ^------ in this table
+ − 66 // ```
+ − 67 // It actually points to the top-level table at the first character,
+ − 68 // not `[table]`. But it is too confusing. To avoid the confusion, the error
+ − 69 // message should explicitly say "key not found in the top-level table",
+ − 70 // or "the parsed file is empty" if there is no content at all (0 bytes in file).
+ − 71 const auto loc = v.location();
+ − 72 if(loc.line() == 1 && loc.region() == 0)
+ − 73 {
+ − 74 // First line with a zero-length region means "empty file".
+ − 75 // The region will be generated at `parse_toml_file` function
+ − 76 // if the file contains no bytes.
+ − 77 throw std::out_of_range(format_underline(concat_to_string(
+ − 78 "key \"", ky, "\" not found in the top-level table"), {
+ − 79 {loc, "the parsed file is empty"}
+ − 80 }));
+ − 81 }
+ − 82 else if(loc.line() == 1 && loc.region() == 1)
+ − 83 {
+ − 84 // Here it assumes that top-level table starts at the first character.
+ − 85 // The region corresponds to the top-level table will be generated at
+ − 86 // `parse_toml_file` function.
+ − 87 // It also assumes that the top-level table size is just one and
+ − 88 // the line number is `1`. It is always satisfied. And those conditions
+ − 89 // are satisfied only if the table is the top-level table.
+ − 90 //
+ − 91 // 1. one-character dot-key at the first line
+ − 92 // ```toml
+ − 93 // a.b = "c"
+ − 94 // ```
+ − 95 // toml11 counts whole key as the table key. Here, `a.b` is the region
+ − 96 // of the table "a". It could be counter intuitive, but it works.
+ − 97 // The size of the region is 3, not 1. The above example is the shortest
+ − 98 // dot-key example. The size cannot be 1.
+ − 99 //
+ − 100 // 2. one-character inline-table at the first line
+ − 101 // ```toml
+ − 102 // a = {b = "c"}
+ − 103 // ```
+ − 104 // toml11 considers the inline table body as the table region. Here,
+ − 105 // `{b = "c"}` is the region of the table "a". The size of the region
+ − 106 // is 9, not 1. The shotest inline table still has two characters, `{`
+ − 107 // and `}`. The size cannot be 1.
+ − 108 //
+ − 109 // 3. one-character table declaration at the first line
+ − 110 // ```toml
+ − 111 // [a]
+ − 112 // ```
+ − 113 // toml11 considers the whole table key as the table region. Here,
+ − 114 // `[a]` is the table region. The size is 3, not 1.
+ − 115 //
+ − 116 throw std::out_of_range(format_underline(concat_to_string(
+ − 117 "key \"", ky, "\" not found in the top-level table"), {
+ − 118 {loc, "the top-level table starts here"}
+ − 119 }));
+ − 120 }
+ − 121 else
+ − 122 {
+ − 123 // normal table.
+ − 124 throw std::out_of_range(format_underline(concat_to_string(
+ − 125 "key \"", ky, "\" not found"), { {loc, "in this table"} }));
+ − 126 }
+ − 127 }
+ − 128
+ − 129 // switch by `value_t` at the compile time.
+ − 130 template<value_t T>
+ − 131 struct switch_cast {};
+ − 132 #define TOML11_GENERATE_SWITCH_CASTER(TYPE) \
+ − 133 template<> \
+ − 134 struct switch_cast<value_t::TYPE> \
+ − 135 { \
+ − 136 template<typename Value> \
+ − 137 static typename Value::TYPE##_type& invoke(Value& v) \
+ − 138 { \
+ − 139 return v.as_##TYPE(); \
+ − 140 } \
+ − 141 template<typename Value> \
+ − 142 static typename Value::TYPE##_type const& invoke(const Value& v) \
+ − 143 { \
+ − 144 return v.as_##TYPE(); \
+ − 145 } \
+ − 146 template<typename Value> \
+ − 147 static typename Value::TYPE##_type&& invoke(Value&& v) \
+ − 148 { \
+ − 149 return std::move(v).as_##TYPE(); \
+ − 150 } \
+ − 151 }; \
+ − 152 /**/
+ − 153 TOML11_GENERATE_SWITCH_CASTER(boolean)
+ − 154 TOML11_GENERATE_SWITCH_CASTER(integer)
+ − 155 TOML11_GENERATE_SWITCH_CASTER(floating)
+ − 156 TOML11_GENERATE_SWITCH_CASTER(string)
+ − 157 TOML11_GENERATE_SWITCH_CASTER(offset_datetime)
+ − 158 TOML11_GENERATE_SWITCH_CASTER(local_datetime)
+ − 159 TOML11_GENERATE_SWITCH_CASTER(local_date)
+ − 160 TOML11_GENERATE_SWITCH_CASTER(local_time)
+ − 161 TOML11_GENERATE_SWITCH_CASTER(array)
+ − 162 TOML11_GENERATE_SWITCH_CASTER(table)
+ − 163
+ − 164 #undef TOML11_GENERATE_SWITCH_CASTER
+ − 165
+ − 166 }// detail
+ − 167
+ − 168 template<typename Comment, // discard/preserve_comment
+ − 169 template<typename ...> class Table = std::unordered_map,
+ − 170 template<typename ...> class Array = std::vector>
+ − 171 class basic_value
+ − 172 {
+ − 173 template<typename T, typename U>
+ − 174 static void assigner(T& dst, U&& v)
+ − 175 {
+ − 176 const auto tmp = ::new(std::addressof(dst)) T(std::forward<U>(v));
+ − 177 assert(tmp == std::addressof(dst));
+ − 178 (void)tmp;
+ − 179 }
+ − 180
+ − 181 using region_base = detail::region_base;
+ − 182
+ − 183 template<typename C, template<typename ...> class T,
+ − 184 template<typename ...> class A>
+ − 185 friend class basic_value;
+ − 186
+ − 187 public:
+ − 188
+ − 189 using comment_type = Comment;
+ − 190 using key_type = ::toml::key;
+ − 191 using value_type = basic_value<comment_type, Table, Array>;
+ − 192 using boolean_type = ::toml::boolean;
+ − 193 using integer_type = ::toml::integer;
+ − 194 using floating_type = ::toml::floating;
+ − 195 using string_type = ::toml::string;
+ − 196 using local_time_type = ::toml::local_time;
+ − 197 using local_date_type = ::toml::local_date;
+ − 198 using local_datetime_type = ::toml::local_datetime;
+ − 199 using offset_datetime_type = ::toml::offset_datetime;
+ − 200 using array_type = Array<value_type>;
+ − 201 using table_type = Table<key_type, value_type>;
+ − 202
+ − 203 public:
+ − 204
+ − 205 basic_value() noexcept
+ − 206 : type_(value_t::empty),
+ − 207 region_info_(std::make_shared<region_base>(region_base{}))
+ − 208 {}
+ − 209 ~basic_value() noexcept {this->cleanup();}
+ − 210
+ − 211 basic_value(const basic_value& v)
+ − 212 : type_(v.type()), region_info_(v.region_info_), comments_(v.comments_)
+ − 213 {
+ − 214 switch(v.type())
+ − 215 {
+ − 216 case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
+ − 217 case value_t::integer : assigner(integer_ , v.integer_ ); break;
+ − 218 case value_t::floating : assigner(floating_ , v.floating_ ); break;
+ − 219 case value_t::string : assigner(string_ , v.string_ ); break;
+ − 220 case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+ − 221 case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+ − 222 case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
+ − 223 case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
+ − 224 case value_t::array : assigner(array_ , v.array_ ); break;
+ − 225 case value_t::table : assigner(table_ , v.table_ ); break;
+ − 226 default: break;
+ − 227 }
+ − 228 }
+ − 229 basic_value(basic_value&& v)
+ − 230 : type_(v.type()), region_info_(std::move(v.region_info_)),
+ − 231 comments_(std::move(v.comments_))
+ − 232 {
+ − 233 switch(this->type_) // here this->type_ is already initialized
+ − 234 {
+ − 235 case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break;
+ − 236 case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break;
+ − 237 case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break;
+ − 238 case value_t::string : assigner(string_ , std::move(v.string_ )); break;
+ − 239 case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
+ − 240 case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
+ − 241 case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break;
+ − 242 case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break;
+ − 243 case value_t::array : assigner(array_ , std::move(v.array_ )); break;
+ − 244 case value_t::table : assigner(table_ , std::move(v.table_ )); break;
+ − 245 default: break;
+ − 246 }
+ − 247 }
+ − 248 basic_value& operator=(const basic_value& v)
+ − 249 {
+ − 250 if(this == std::addressof(v)) {return *this;}
+ − 251 this->cleanup();
+ − 252 this->region_info_ = v.region_info_;
+ − 253 this->comments_ = v.comments_;
+ − 254 this->type_ = v.type();
+ − 255 switch(this->type_)
+ − 256 {
+ − 257 case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
+ − 258 case value_t::integer : assigner(integer_ , v.integer_ ); break;
+ − 259 case value_t::floating : assigner(floating_ , v.floating_ ); break;
+ − 260 case value_t::string : assigner(string_ , v.string_ ); break;
+ − 261 case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+ − 262 case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+ − 263 case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
+ − 264 case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
+ − 265 case value_t::array : assigner(array_ , v.array_ ); break;
+ − 266 case value_t::table : assigner(table_ , v.table_ ); break;
+ − 267 default: break;
+ − 268 }
+ − 269 return *this;
+ − 270 }
+ − 271 basic_value& operator=(basic_value&& v)
+ − 272 {
+ − 273 if(this == std::addressof(v)) {return *this;}
+ − 274 this->cleanup();
+ − 275 this->region_info_ = std::move(v.region_info_);
+ − 276 this->comments_ = std::move(v.comments_);
+ − 277 this->type_ = v.type();
+ − 278 switch(this->type_)
+ − 279 {
+ − 280 case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break;
+ − 281 case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break;
+ − 282 case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break;
+ − 283 case value_t::string : assigner(string_ , std::move(v.string_ )); break;
+ − 284 case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
+ − 285 case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
+ − 286 case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break;
+ − 287 case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break;
+ − 288 case value_t::array : assigner(array_ , std::move(v.array_ )); break;
+ − 289 case value_t::table : assigner(table_ , std::move(v.table_ )); break;
+ − 290 default: break;
+ − 291 }
+ − 292 return *this;
+ − 293 }
+ − 294
+ − 295 // overwrite comments ----------------------------------------------------
+ − 296
+ − 297 basic_value(const basic_value& v, std::vector<std::string> com)
+ − 298 : type_(v.type()), region_info_(v.region_info_),
+ − 299 comments_(std::move(com))
+ − 300 {
+ − 301 switch(v.type())
+ − 302 {
+ − 303 case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
+ − 304 case value_t::integer : assigner(integer_ , v.integer_ ); break;
+ − 305 case value_t::floating : assigner(floating_ , v.floating_ ); break;
+ − 306 case value_t::string : assigner(string_ , v.string_ ); break;
+ − 307 case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+ − 308 case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+ − 309 case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
+ − 310 case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
+ − 311 case value_t::array : assigner(array_ , v.array_ ); break;
+ − 312 case value_t::table : assigner(table_ , v.table_ ); break;
+ − 313 default: break;
+ − 314 }
+ − 315 }
+ − 316
+ − 317 basic_value(basic_value&& v, std::vector<std::string> com)
+ − 318 : type_(v.type()), region_info_(std::move(v.region_info_)),
+ − 319 comments_(std::move(com))
+ − 320 {
+ − 321 switch(this->type_) // here this->type_ is already initialized
+ − 322 {
+ − 323 case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break;
+ − 324 case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break;
+ − 325 case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break;
+ − 326 case value_t::string : assigner(string_ , std::move(v.string_ )); break;
+ − 327 case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
+ − 328 case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
+ − 329 case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break;
+ − 330 case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break;
+ − 331 case value_t::array : assigner(array_ , std::move(v.array_ )); break;
+ − 332 case value_t::table : assigner(table_ , std::move(v.table_ )); break;
+ − 333 default: break;
+ − 334 }
+ − 335 }
+ − 336
+ − 337 // -----------------------------------------------------------------------
+ − 338 // conversion between different basic_values.
+ − 339 template<typename C,
+ − 340 template<typename ...> class T,
+ − 341 template<typename ...> class A>
+ − 342 basic_value(const basic_value<C, T, A>& v)
+ − 343 : type_(v.type()), region_info_(v.region_info_), comments_(v.comments())
+ − 344 {
+ − 345 switch(v.type())
+ − 346 {
+ − 347 case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
+ − 348 case value_t::integer : assigner(integer_ , v.integer_ ); break;
+ − 349 case value_t::floating : assigner(floating_ , v.floating_ ); break;
+ − 350 case value_t::string : assigner(string_ , v.string_ ); break;
+ − 351 case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+ − 352 case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+ − 353 case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
+ − 354 case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
+ − 355 case value_t::array :
+ − 356 {
+ − 357 array_type tmp(v.as_array(std::nothrow).begin(),
+ − 358 v.as_array(std::nothrow).end());
+ − 359 assigner(array_, std::move(tmp));
+ − 360 break;
+ − 361 }
+ − 362 case value_t::table :
+ − 363 {
+ − 364 table_type tmp(v.as_table(std::nothrow).begin(),
+ − 365 v.as_table(std::nothrow).end());
+ − 366 assigner(table_, std::move(tmp));
+ − 367 break;
+ − 368 }
+ − 369 default: break;
+ − 370 }
+ − 371 }
+ − 372 template<typename C,
+ − 373 template<typename ...> class T,
+ − 374 template<typename ...> class A>
+ − 375 basic_value(const basic_value<C, T, A>& v, std::vector<std::string> com)
+ − 376 : type_(v.type()), region_info_(v.region_info_),
+ − 377 comments_(std::move(com))
+ − 378 {
+ − 379 switch(v.type())
+ − 380 {
+ − 381 case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
+ − 382 case value_t::integer : assigner(integer_ , v.integer_ ); break;
+ − 383 case value_t::floating : assigner(floating_ , v.floating_ ); break;
+ − 384 case value_t::string : assigner(string_ , v.string_ ); break;
+ − 385 case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+ − 386 case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+ − 387 case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
+ − 388 case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
+ − 389 case value_t::array :
+ − 390 {
+ − 391 array_type tmp(v.as_array(std::nothrow).begin(),
+ − 392 v.as_array(std::nothrow).end());
+ − 393 assigner(array_, std::move(tmp));
+ − 394 break;
+ − 395 }
+ − 396 case value_t::table :
+ − 397 {
+ − 398 table_type tmp(v.as_table(std::nothrow).begin(),
+ − 399 v.as_table(std::nothrow).end());
+ − 400 assigner(table_, std::move(tmp));
+ − 401 break;
+ − 402 }
+ − 403 default: break;
+ − 404 }
+ − 405 }
+ − 406 template<typename C,
+ − 407 template<typename ...> class T,
+ − 408 template<typename ...> class A>
+ − 409 basic_value& operator=(const basic_value<C, T, A>& v)
+ − 410 {
+ − 411 this->region_info_ = v.region_info_;
+ − 412 this->comments_ = comment_type(v.comments());
+ − 413 this->type_ = v.type();
+ − 414 switch(v.type())
+ − 415 {
+ − 416 case value_t::boolean : assigner(boolean_ , v.boolean_ ); break;
+ − 417 case value_t::integer : assigner(integer_ , v.integer_ ); break;
+ − 418 case value_t::floating : assigner(floating_ , v.floating_ ); break;
+ − 419 case value_t::string : assigner(string_ , v.string_ ); break;
+ − 420 case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+ − 421 case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+ − 422 case value_t::local_date : assigner(local_date_ , v.local_date_ ); break;
+ − 423 case value_t::local_time : assigner(local_time_ , v.local_time_ ); break;
+ − 424 case value_t::array :
+ − 425 {
+ − 426 array_type tmp(v.as_array(std::nothrow).begin(),
+ − 427 v.as_array(std::nothrow).end());
+ − 428 assigner(array_, std::move(tmp));
+ − 429 break;
+ − 430 }
+ − 431 case value_t::table :
+ − 432 {
+ − 433 table_type tmp(v.as_table(std::nothrow).begin(),
+ − 434 v.as_table(std::nothrow).end());
+ − 435 assigner(table_, std::move(tmp));
+ − 436 break;
+ − 437 }
+ − 438 default: break;
+ − 439 }
+ − 440 return *this;
+ − 441 }
+ − 442
+ − 443 // boolean ==============================================================
+ − 444
+ − 445 basic_value(boolean b)
+ − 446 : type_(value_t::boolean),
+ − 447 region_info_(std::make_shared<region_base>(region_base{}))
+ − 448 {
+ − 449 assigner(this->boolean_, b);
+ − 450 }
+ − 451 basic_value& operator=(boolean b)
+ − 452 {
+ − 453 this->cleanup();
+ − 454 this->type_ = value_t::boolean;
+ − 455 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 456 assigner(this->boolean_, b);
+ − 457 return *this;
+ − 458 }
+ − 459 basic_value(boolean b, std::vector<std::string> com)
+ − 460 : type_(value_t::boolean),
+ − 461 region_info_(std::make_shared<region_base>(region_base{})),
+ − 462 comments_(std::move(com))
+ − 463 {
+ − 464 assigner(this->boolean_, b);
+ − 465 }
+ − 466
+ − 467 // integer ==============================================================
+ − 468
+ − 469 template<typename T, typename std::enable_if<detail::conjunction<
+ − 470 std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
+ − 471 std::nullptr_t>::type = nullptr>
+ − 472 basic_value(T i)
+ − 473 : type_(value_t::integer),
+ − 474 region_info_(std::make_shared<region_base>(region_base{}))
+ − 475 {
+ − 476 assigner(this->integer_, static_cast<integer>(i));
+ − 477 }
+ − 478
+ − 479 template<typename T, typename std::enable_if<detail::conjunction<
+ − 480 std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
+ − 481 std::nullptr_t>::type = nullptr>
+ − 482 basic_value& operator=(T i)
+ − 483 {
+ − 484 this->cleanup();
+ − 485 this->type_ = value_t::integer;
+ − 486 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 487 assigner(this->integer_, static_cast<integer>(i));
+ − 488 return *this;
+ − 489 }
+ − 490
+ − 491 template<typename T, typename std::enable_if<detail::conjunction<
+ − 492 std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
+ − 493 std::nullptr_t>::type = nullptr>
+ − 494 basic_value(T i, std::vector<std::string> com)
+ − 495 : type_(value_t::integer),
+ − 496 region_info_(std::make_shared<region_base>(region_base{})),
+ − 497 comments_(std::move(com))
+ − 498 {
+ − 499 assigner(this->integer_, static_cast<integer>(i));
+ − 500 }
+ − 501
+ − 502 // floating =============================================================
+ − 503
+ − 504 template<typename T, typename std::enable_if<
+ − 505 std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
+ − 506 basic_value(T f)
+ − 507 : type_(value_t::floating),
+ − 508 region_info_(std::make_shared<region_base>(region_base{}))
+ − 509 {
+ − 510 assigner(this->floating_, static_cast<floating>(f));
+ − 511 }
+ − 512
+ − 513
+ − 514 template<typename T, typename std::enable_if<
+ − 515 std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
+ − 516 basic_value& operator=(T f)
+ − 517 {
+ − 518 this->cleanup();
+ − 519 this->type_ = value_t::floating;
+ − 520 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 521 assigner(this->floating_, static_cast<floating>(f));
+ − 522 return *this;
+ − 523 }
+ − 524
+ − 525 template<typename T, typename std::enable_if<
+ − 526 std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
+ − 527 basic_value(T f, std::vector<std::string> com)
+ − 528 : type_(value_t::floating),
+ − 529 region_info_(std::make_shared<region_base>(region_base{})),
+ − 530 comments_(std::move(com))
+ − 531 {
+ − 532 assigner(this->floating_, f);
+ − 533 }
+ − 534
+ − 535 // string ===============================================================
+ − 536
+ − 537 basic_value(toml::string s)
+ − 538 : type_(value_t::string),
+ − 539 region_info_(std::make_shared<region_base>(region_base{}))
+ − 540 {
+ − 541 assigner(this->string_, std::move(s));
+ − 542 }
+ − 543 basic_value& operator=(toml::string s)
+ − 544 {
+ − 545 this->cleanup();
+ − 546 this->type_ = value_t::string ;
+ − 547 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 548 assigner(this->string_, s);
+ − 549 return *this;
+ − 550 }
+ − 551 basic_value(toml::string s, std::vector<std::string> com)
+ − 552 : type_(value_t::string),
+ − 553 region_info_(std::make_shared<region_base>(region_base{})),
+ − 554 comments_(std::move(com))
+ − 555 {
+ − 556 assigner(this->string_, std::move(s));
+ − 557 }
+ − 558
+ − 559 basic_value(std::string s)
+ − 560 : type_(value_t::string),
+ − 561 region_info_(std::make_shared<region_base>(region_base{}))
+ − 562 {
+ − 563 assigner(this->string_, toml::string(std::move(s)));
+ − 564 }
+ − 565 basic_value& operator=(std::string s)
+ − 566 {
+ − 567 this->cleanup();
+ − 568 this->type_ = value_t::string ;
+ − 569 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 570 assigner(this->string_, toml::string(std::move(s)));
+ − 571 return *this;
+ − 572 }
+ − 573 basic_value(std::string s, string_t kind)
+ − 574 : type_(value_t::string),
+ − 575 region_info_(std::make_shared<region_base>(region_base{}))
+ − 576 {
+ − 577 assigner(this->string_, toml::string(std::move(s), kind));
+ − 578 }
+ − 579 basic_value(std::string s, std::vector<std::string> com)
+ − 580 : type_(value_t::string),
+ − 581 region_info_(std::make_shared<region_base>(region_base{})),
+ − 582 comments_(std::move(com))
+ − 583 {
+ − 584 assigner(this->string_, toml::string(std::move(s)));
+ − 585 }
+ − 586 basic_value(std::string s, string_t kind, std::vector<std::string> com)
+ − 587 : type_(value_t::string),
+ − 588 region_info_(std::make_shared<region_base>(region_base{})),
+ − 589 comments_(std::move(com))
+ − 590 {
+ − 591 assigner(this->string_, toml::string(std::move(s), kind));
+ − 592 }
+ − 593
+ − 594 basic_value(const char* s)
+ − 595 : type_(value_t::string),
+ − 596 region_info_(std::make_shared<region_base>(region_base{}))
+ − 597 {
+ − 598 assigner(this->string_, toml::string(std::string(s)));
+ − 599 }
+ − 600 basic_value& operator=(const char* s)
+ − 601 {
+ − 602 this->cleanup();
+ − 603 this->type_ = value_t::string ;
+ − 604 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 605 assigner(this->string_, toml::string(std::string(s)));
+ − 606 return *this;
+ − 607 }
+ − 608 basic_value(const char* s, string_t kind)
+ − 609 : type_(value_t::string),
+ − 610 region_info_(std::make_shared<region_base>(region_base{}))
+ − 611 {
+ − 612 assigner(this->string_, toml::string(std::string(s), kind));
+ − 613 }
+ − 614 basic_value(const char* s, std::vector<std::string> com)
+ − 615 : type_(value_t::string),
+ − 616 region_info_(std::make_shared<region_base>(region_base{})),
+ − 617 comments_(std::move(com))
+ − 618 {
+ − 619 assigner(this->string_, toml::string(std::string(s)));
+ − 620 }
+ − 621 basic_value(const char* s, string_t kind, std::vector<std::string> com)
+ − 622 : type_(value_t::string),
+ − 623 region_info_(std::make_shared<region_base>(region_base{})),
+ − 624 comments_(std::move(com))
+ − 625 {
+ − 626 assigner(this->string_, toml::string(std::string(s), kind));
+ − 627 }
+ − 628
+ − 629 #if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0
+ − 630 basic_value(std::string_view s)
+ − 631 : type_(value_t::string),
+ − 632 region_info_(std::make_shared<region_base>(region_base{}))
+ − 633 {
+ − 634 assigner(this->string_, toml::string(s));
+ − 635 }
+ − 636 basic_value& operator=(std::string_view s)
+ − 637 {
+ − 638 this->cleanup();
+ − 639 this->type_ = value_t::string ;
+ − 640 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 641 assigner(this->string_, toml::string(s));
+ − 642 return *this;
+ − 643 }
+ − 644 basic_value(std::string_view s, std::vector<std::string> com)
+ − 645 : type_(value_t::string),
+ − 646 region_info_(std::make_shared<region_base>(region_base{})),
+ − 647 comments_(std::move(com))
+ − 648 {
+ − 649 assigner(this->string_, toml::string(s));
+ − 650 }
+ − 651 basic_value(std::string_view s, string_t kind)
+ − 652 : type_(value_t::string),
+ − 653 region_info_(std::make_shared<region_base>(region_base{}))
+ − 654 {
+ − 655 assigner(this->string_, toml::string(s, kind));
+ − 656 }
+ − 657 basic_value(std::string_view s, string_t kind, std::vector<std::string> com)
+ − 658 : type_(value_t::string),
+ − 659 region_info_(std::make_shared<region_base>(region_base{})),
+ − 660 comments_(std::move(com))
+ − 661 {
+ − 662 assigner(this->string_, toml::string(s, kind));
+ − 663 }
+ − 664 #endif
+ − 665
+ − 666 // local date ===========================================================
+ − 667
+ − 668 basic_value(const local_date& ld)
+ − 669 : type_(value_t::local_date),
+ − 670 region_info_(std::make_shared<region_base>(region_base{}))
+ − 671 {
+ − 672 assigner(this->local_date_, ld);
+ − 673 }
+ − 674 basic_value& operator=(const local_date& ld)
+ − 675 {
+ − 676 this->cleanup();
+ − 677 this->type_ = value_t::local_date;
+ − 678 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 679 assigner(this->local_date_, ld);
+ − 680 return *this;
+ − 681 }
+ − 682 basic_value(const local_date& ld, std::vector<std::string> com)
+ − 683 : type_(value_t::local_date),
+ − 684 region_info_(std::make_shared<region_base>(region_base{})),
+ − 685 comments_(std::move(com))
+ − 686 {
+ − 687 assigner(this->local_date_, ld);
+ − 688 }
+ − 689
+ − 690 // local time ===========================================================
+ − 691
+ − 692 basic_value(const local_time& lt)
+ − 693 : type_(value_t::local_time),
+ − 694 region_info_(std::make_shared<region_base>(region_base{}))
+ − 695 {
+ − 696 assigner(this->local_time_, lt);
+ − 697 }
+ − 698 basic_value(const local_time& lt, std::vector<std::string> com)
+ − 699 : type_(value_t::local_time),
+ − 700 region_info_(std::make_shared<region_base>(region_base{})),
+ − 701 comments_(std::move(com))
+ − 702 {
+ − 703 assigner(this->local_time_, lt);
+ − 704 }
+ − 705 basic_value& operator=(const local_time& lt)
+ − 706 {
+ − 707 this->cleanup();
+ − 708 this->type_ = value_t::local_time;
+ − 709 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 710 assigner(this->local_time_, lt);
+ − 711 return *this;
+ − 712 }
+ − 713
+ − 714 template<typename Rep, typename Period>
+ − 715 basic_value(const std::chrono::duration<Rep, Period>& dur)
+ − 716 : type_(value_t::local_time),
+ − 717 region_info_(std::make_shared<region_base>(region_base{}))
+ − 718 {
+ − 719 assigner(this->local_time_, local_time(dur));
+ − 720 }
+ − 721 template<typename Rep, typename Period>
+ − 722 basic_value(const std::chrono::duration<Rep, Period>& dur,
+ − 723 std::vector<std::string> com)
+ − 724 : type_(value_t::local_time),
+ − 725 region_info_(std::make_shared<region_base>(region_base{})),
+ − 726 comments_(std::move(com))
+ − 727 {
+ − 728 assigner(this->local_time_, local_time(dur));
+ − 729 }
+ − 730 template<typename Rep, typename Period>
+ − 731 basic_value& operator=(const std::chrono::duration<Rep, Period>& dur)
+ − 732 {
+ − 733 this->cleanup();
+ − 734 this->type_ = value_t::local_time;
+ − 735 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 736 assigner(this->local_time_, local_time(dur));
+ − 737 return *this;
+ − 738 }
+ − 739
+ − 740 // local datetime =======================================================
+ − 741
+ − 742 basic_value(const local_datetime& ldt)
+ − 743 : type_(value_t::local_datetime),
+ − 744 region_info_(std::make_shared<region_base>(region_base{}))
+ − 745 {
+ − 746 assigner(this->local_datetime_, ldt);
+ − 747 }
+ − 748 basic_value(const local_datetime& ldt, std::vector<std::string> com)
+ − 749 : type_(value_t::local_datetime),
+ − 750 region_info_(std::make_shared<region_base>(region_base{})),
+ − 751 comments_(std::move(com))
+ − 752 {
+ − 753 assigner(this->local_datetime_, ldt);
+ − 754 }
+ − 755 basic_value& operator=(const local_datetime& ldt)
+ − 756 {
+ − 757 this->cleanup();
+ − 758 this->type_ = value_t::local_datetime;
+ − 759 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 760 assigner(this->local_datetime_, ldt);
+ − 761 return *this;
+ − 762 }
+ − 763
+ − 764 // offset datetime ======================================================
+ − 765
+ − 766 basic_value(const offset_datetime& odt)
+ − 767 : type_(value_t::offset_datetime),
+ − 768 region_info_(std::make_shared<region_base>(region_base{}))
+ − 769 {
+ − 770 assigner(this->offset_datetime_, odt);
+ − 771 }
+ − 772 basic_value(const offset_datetime& odt, std::vector<std::string> com)
+ − 773 : type_(value_t::offset_datetime),
+ − 774 region_info_(std::make_shared<region_base>(region_base{})),
+ − 775 comments_(std::move(com))
+ − 776 {
+ − 777 assigner(this->offset_datetime_, odt);
+ − 778 }
+ − 779 basic_value& operator=(const offset_datetime& odt)
+ − 780 {
+ − 781 this->cleanup();
+ − 782 this->type_ = value_t::offset_datetime;
+ − 783 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 784 assigner(this->offset_datetime_, odt);
+ − 785 return *this;
+ − 786 }
+ − 787 basic_value(const std::chrono::system_clock::time_point& tp)
+ − 788 : type_(value_t::offset_datetime),
+ − 789 region_info_(std::make_shared<region_base>(region_base{}))
+ − 790 {
+ − 791 assigner(this->offset_datetime_, offset_datetime(tp));
+ − 792 }
+ − 793 basic_value(const std::chrono::system_clock::time_point& tp,
+ − 794 std::vector<std::string> com)
+ − 795 : type_(value_t::offset_datetime),
+ − 796 region_info_(std::make_shared<region_base>(region_base{})),
+ − 797 comments_(std::move(com))
+ − 798 {
+ − 799 assigner(this->offset_datetime_, offset_datetime(tp));
+ − 800 }
+ − 801 basic_value& operator=(const std::chrono::system_clock::time_point& tp)
+ − 802 {
+ − 803 this->cleanup();
+ − 804 this->type_ = value_t::offset_datetime;
+ − 805 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 806 assigner(this->offset_datetime_, offset_datetime(tp));
+ − 807 return *this;
+ − 808 }
+ − 809
+ − 810 // array ================================================================
+ − 811
+ − 812 basic_value(const array_type& ary)
+ − 813 : type_(value_t::array),
+ − 814 region_info_(std::make_shared<region_base>(region_base{}))
+ − 815 {
+ − 816 assigner(this->array_, ary);
+ − 817 }
+ − 818 basic_value(const array_type& ary, std::vector<std::string> com)
+ − 819 : type_(value_t::array),
+ − 820 region_info_(std::make_shared<region_base>(region_base{})),
+ − 821 comments_(std::move(com))
+ − 822 {
+ − 823 assigner(this->array_, ary);
+ − 824 }
+ − 825 basic_value& operator=(const array_type& ary)
+ − 826 {
+ − 827 this->cleanup();
+ − 828 this->type_ = value_t::array ;
+ − 829 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 830 assigner(this->array_, ary);
+ − 831 return *this;
+ − 832 }
+ − 833
+ − 834 // array (initializer_list) ----------------------------------------------
+ − 835
+ − 836 template<typename T, typename std::enable_if<
+ − 837 std::is_convertible<T, value_type>::value,
+ − 838 std::nullptr_t>::type = nullptr>
+ − 839 basic_value(std::initializer_list<T> list)
+ − 840 : type_(value_t::array),
+ − 841 region_info_(std::make_shared<region_base>(region_base{}))
+ − 842 {
+ − 843 array_type ary(list.begin(), list.end());
+ − 844 assigner(this->array_, std::move(ary));
+ − 845 }
+ − 846 template<typename T, typename std::enable_if<
+ − 847 std::is_convertible<T, value_type>::value,
+ − 848 std::nullptr_t>::type = nullptr>
+ − 849 basic_value(std::initializer_list<T> list, std::vector<std::string> com)
+ − 850 : type_(value_t::array),
+ − 851 region_info_(std::make_shared<region_base>(region_base{})),
+ − 852 comments_(std::move(com))
+ − 853 {
+ − 854 array_type ary(list.begin(), list.end());
+ − 855 assigner(this->array_, std::move(ary));
+ − 856 }
+ − 857 template<typename T, typename std::enable_if<
+ − 858 std::is_convertible<T, value_type>::value,
+ − 859 std::nullptr_t>::type = nullptr>
+ − 860 basic_value& operator=(std::initializer_list<T> list)
+ − 861 {
+ − 862 this->cleanup();
+ − 863 this->type_ = value_t::array;
+ − 864 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 865
+ − 866 array_type ary(list.begin(), list.end());
+ − 867 assigner(this->array_, std::move(ary));
+ − 868 return *this;
+ − 869 }
+ − 870
+ − 871 // array (STL Containers) ------------------------------------------------
+ − 872
+ − 873 template<typename T, typename std::enable_if<detail::conjunction<
+ − 874 detail::negation<std::is_same<T, array_type>>,
+ − 875 detail::is_container<T>
+ − 876 >::value, std::nullptr_t>::type = nullptr>
+ − 877 basic_value(const T& list)
+ − 878 : type_(value_t::array),
+ − 879 region_info_(std::make_shared<region_base>(region_base{}))
+ − 880 {
+ − 881 static_assert(std::is_convertible<typename T::value_type, value_type>::value,
+ − 882 "elements of a container should be convertible to toml::value");
+ − 883
+ − 884 array_type ary(list.size());
+ − 885 std::copy(list.begin(), list.end(), ary.begin());
+ − 886 assigner(this->array_, std::move(ary));
+ − 887 }
+ − 888 template<typename T, typename std::enable_if<detail::conjunction<
+ − 889 detail::negation<std::is_same<T, array_type>>,
+ − 890 detail::is_container<T>
+ − 891 >::value, std::nullptr_t>::type = nullptr>
+ − 892 basic_value(const T& list, std::vector<std::string> com)
+ − 893 : type_(value_t::array),
+ − 894 region_info_(std::make_shared<region_base>(region_base{})),
+ − 895 comments_(std::move(com))
+ − 896 {
+ − 897 static_assert(std::is_convertible<typename T::value_type, value_type>::value,
+ − 898 "elements of a container should be convertible to toml::value");
+ − 899
+ − 900 array_type ary(list.size());
+ − 901 std::copy(list.begin(), list.end(), ary.begin());
+ − 902 assigner(this->array_, std::move(ary));
+ − 903 }
+ − 904 template<typename T, typename std::enable_if<detail::conjunction<
+ − 905 detail::negation<std::is_same<T, array_type>>,
+ − 906 detail::is_container<T>
+ − 907 >::value, std::nullptr_t>::type = nullptr>
+ − 908 basic_value& operator=(const T& list)
+ − 909 {
+ − 910 static_assert(std::is_convertible<typename T::value_type, value_type>::value,
+ − 911 "elements of a container should be convertible to toml::value");
+ − 912
+ − 913 this->cleanup();
+ − 914 this->type_ = value_t::array;
+ − 915 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 916
+ − 917 array_type ary(list.size());
+ − 918 std::copy(list.begin(), list.end(), ary.begin());
+ − 919 assigner(this->array_, std::move(ary));
+ − 920 return *this;
+ − 921 }
+ − 922
+ − 923 // table ================================================================
+ − 924
+ − 925 basic_value(const table_type& tab)
+ − 926 : type_(value_t::table),
+ − 927 region_info_(std::make_shared<region_base>(region_base{}))
+ − 928 {
+ − 929 assigner(this->table_, tab);
+ − 930 }
+ − 931 basic_value(const table_type& tab, std::vector<std::string> com)
+ − 932 : type_(value_t::table),
+ − 933 region_info_(std::make_shared<region_base>(region_base{})),
+ − 934 comments_(std::move(com))
+ − 935 {
+ − 936 assigner(this->table_, tab);
+ − 937 }
+ − 938 basic_value& operator=(const table_type& tab)
+ − 939 {
+ − 940 this->cleanup();
+ − 941 this->type_ = value_t::table;
+ − 942 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 943 assigner(this->table_, tab);
+ − 944 return *this;
+ − 945 }
+ − 946
+ − 947 // initializer-list ------------------------------------------------------
+ − 948
+ − 949 basic_value(std::initializer_list<std::pair<key, basic_value>> list)
+ − 950 : type_(value_t::table),
+ − 951 region_info_(std::make_shared<region_base>(region_base{}))
+ − 952 {
+ − 953 table_type tab;
+ − 954 for(const auto& elem : list) {tab[elem.first] = elem.second;}
+ − 955 assigner(this->table_, std::move(tab));
+ − 956 }
+ − 957
+ − 958 basic_value(std::initializer_list<std::pair<key, basic_value>> list,
+ − 959 std::vector<std::string> com)
+ − 960 : type_(value_t::table),
+ − 961 region_info_(std::make_shared<region_base>(region_base{})),
+ − 962 comments_(std::move(com))
+ − 963 {
+ − 964 table_type tab;
+ − 965 for(const auto& elem : list) {tab[elem.first] = elem.second;}
+ − 966 assigner(this->table_, std::move(tab));
+ − 967 }
+ − 968 basic_value& operator=(std::initializer_list<std::pair<key, basic_value>> list)
+ − 969 {
+ − 970 this->cleanup();
+ − 971 this->type_ = value_t::table;
+ − 972 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 973
+ − 974 table_type tab;
+ − 975 for(const auto& elem : list) {tab[elem.first] = elem.second;}
+ − 976 assigner(this->table_, std::move(tab));
+ − 977 return *this;
+ − 978 }
+ − 979
+ − 980 // other table-like -----------------------------------------------------
+ − 981
+ − 982 template<typename Map, typename std::enable_if<detail::conjunction<
+ − 983 detail::negation<std::is_same<Map, table_type>>,
+ − 984 detail::is_map<Map>
+ − 985 >::value, std::nullptr_t>::type = nullptr>
+ − 986 basic_value(const Map& mp)
+ − 987 : type_(value_t::table),
+ − 988 region_info_(std::make_shared<region_base>(region_base{}))
+ − 989 {
+ − 990 table_type tab;
+ − 991 for(const auto& elem : mp) {tab[elem.first] = elem.second;}
+ − 992 assigner(this->table_, std::move(tab));
+ − 993 }
+ − 994 template<typename Map, typename std::enable_if<detail::conjunction<
+ − 995 detail::negation<std::is_same<Map, table_type>>,
+ − 996 detail::is_map<Map>
+ − 997 >::value, std::nullptr_t>::type = nullptr>
+ − 998 basic_value(const Map& mp, std::vector<std::string> com)
+ − 999 : type_(value_t::table),
+ − 1000 region_info_(std::make_shared<region_base>(region_base{})),
+ − 1001 comments_(std::move(com))
+ − 1002 {
+ − 1003 table_type tab;
+ − 1004 for(const auto& elem : mp) {tab[elem.first] = elem.second;}
+ − 1005 assigner(this->table_, std::move(tab));
+ − 1006 }
+ − 1007 template<typename Map, typename std::enable_if<detail::conjunction<
+ − 1008 detail::negation<std::is_same<Map, table_type>>,
+ − 1009 detail::is_map<Map>
+ − 1010 >::value, std::nullptr_t>::type = nullptr>
+ − 1011 basic_value& operator=(const Map& mp)
+ − 1012 {
+ − 1013 this->cleanup();
+ − 1014 this->type_ = value_t::table;
+ − 1015 this->region_info_ = std::make_shared<region_base>(region_base{});
+ − 1016
+ − 1017 table_type tab;
+ − 1018 for(const auto& elem : mp) {tab[elem.first] = elem.second;}
+ − 1019 assigner(this->table_, std::move(tab));
+ − 1020 return *this;
+ − 1021 }
+ − 1022
+ − 1023 // user-defined =========================================================
+ − 1024
+ − 1025 // convert using into_toml() method -------------------------------------
+ − 1026
+ − 1027 template<typename T, typename std::enable_if<
+ − 1028 detail::has_into_toml_method<T>::value, std::nullptr_t>::type = nullptr>
+ − 1029 basic_value(const T& ud): basic_value(ud.into_toml()) {}
+ − 1030
+ − 1031 template<typename T, typename std::enable_if<
+ − 1032 detail::has_into_toml_method<T>::value, std::nullptr_t>::type = nullptr>
+ − 1033 basic_value(const T& ud, std::vector<std::string> com)
+ − 1034 : basic_value(ud.into_toml(), std::move(com))
+ − 1035 {}
+ − 1036 template<typename T, typename std::enable_if<
+ − 1037 detail::has_into_toml_method<T>::value, std::nullptr_t>::type = nullptr>
+ − 1038 basic_value& operator=(const T& ud)
+ − 1039 {
+ − 1040 *this = ud.into_toml();
+ − 1041 return *this;
+ − 1042 }
+ − 1043
+ − 1044 // convert using into<T> struct -----------------------------------------
+ − 1045
+ − 1046 template<typename T, std::size_t S = sizeof(::toml::into<T>)>
+ − 1047 basic_value(const T& ud): basic_value(::toml::into<T>::into_toml(ud)) {}
+ − 1048 template<typename T, std::size_t S = sizeof(::toml::into<T>)>
+ − 1049 basic_value(const T& ud, std::vector<std::string> com)
+ − 1050 : basic_value(::toml::into<T>::into_toml(ud), std::move(com))
+ − 1051 {}
+ − 1052 template<typename T, std::size_t S = sizeof(::toml::into<T>)>
+ − 1053 basic_value& operator=(const T& ud)
+ − 1054 {
+ − 1055 *this = ::toml::into<T>::into_toml(ud);
+ − 1056 return *this;
+ − 1057 }
+ − 1058
+ − 1059 // for internal use ------------------------------------------------------
+ − 1060 //
+ − 1061 // Those constructors take detail::region that contains parse result.
+ − 1062
+ − 1063 basic_value(boolean b, detail::region reg, std::vector<std::string> cm)
+ − 1064 : type_(value_t::boolean),
+ − 1065 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1066 comments_(std::move(cm))
+ − 1067 {
+ − 1068 assigner(this->boolean_, b);
+ − 1069 }
+ − 1070 template<typename T, typename std::enable_if<
+ − 1071 detail::conjunction<
+ − 1072 std::is_integral<T>, detail::negation<std::is_same<T, boolean>>
+ − 1073 >::value, std::nullptr_t>::type = nullptr>
+ − 1074 basic_value(T i, detail::region reg, std::vector<std::string> cm)
+ − 1075 : type_(value_t::integer),
+ − 1076 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1077 comments_(std::move(cm))
+ − 1078 {
+ − 1079 assigner(this->integer_, static_cast<integer>(i));
+ − 1080 }
+ − 1081 template<typename T, typename std::enable_if<
+ − 1082 std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
+ − 1083 basic_value(T f, detail::region reg, std::vector<std::string> cm)
+ − 1084 : type_(value_t::floating),
+ − 1085 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1086 comments_(std::move(cm))
+ − 1087 {
+ − 1088 assigner(this->floating_, static_cast<floating>(f));
+ − 1089 }
+ − 1090 basic_value(toml::string s, detail::region reg,
+ − 1091 std::vector<std::string> cm)
+ − 1092 : type_(value_t::string),
+ − 1093 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1094 comments_(std::move(cm))
+ − 1095 {
+ − 1096 assigner(this->string_, std::move(s));
+ − 1097 }
+ − 1098 basic_value(const local_date& ld, detail::region reg,
+ − 1099 std::vector<std::string> cm)
+ − 1100 : type_(value_t::local_date),
+ − 1101 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1102 comments_(std::move(cm))
+ − 1103 {
+ − 1104 assigner(this->local_date_, ld);
+ − 1105 }
+ − 1106 basic_value(const local_time& lt, detail::region reg,
+ − 1107 std::vector<std::string> cm)
+ − 1108 : type_(value_t::local_time),
+ − 1109 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1110 comments_(std::move(cm))
+ − 1111 {
+ − 1112 assigner(this->local_time_, lt);
+ − 1113 }
+ − 1114 basic_value(const local_datetime& ldt, detail::region reg,
+ − 1115 std::vector<std::string> cm)
+ − 1116 : type_(value_t::local_datetime),
+ − 1117 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1118 comments_(std::move(cm))
+ − 1119 {
+ − 1120 assigner(this->local_datetime_, ldt);
+ − 1121 }
+ − 1122 basic_value(const offset_datetime& odt, detail::region reg,
+ − 1123 std::vector<std::string> cm)
+ − 1124 : type_(value_t::offset_datetime),
+ − 1125 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1126 comments_(std::move(cm))
+ − 1127 {
+ − 1128 assigner(this->offset_datetime_, odt);
+ − 1129 }
+ − 1130 basic_value(const array_type& ary, detail::region reg,
+ − 1131 std::vector<std::string> cm)
+ − 1132 : type_(value_t::array),
+ − 1133 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1134 comments_(std::move(cm))
+ − 1135 {
+ − 1136 assigner(this->array_, ary);
+ − 1137 }
+ − 1138 basic_value(const table_type& tab, detail::region reg,
+ − 1139 std::vector<std::string> cm)
+ − 1140 : type_(value_t::table),
+ − 1141 region_info_(std::make_shared<detail::region>(std::move(reg))),
+ − 1142 comments_(std::move(cm))
+ − 1143 {
+ − 1144 assigner(this->table_, tab);
+ − 1145 }
+ − 1146
+ − 1147 template<typename T, typename std::enable_if<
+ − 1148 detail::is_exact_toml_type<T, value_type>::value,
+ − 1149 std::nullptr_t>::type = nullptr>
+ − 1150 basic_value(std::pair<T, detail::region> parse_result, std::vector<std::string> com)
+ − 1151 : basic_value(std::move(parse_result.first),
+ − 1152 std::move(parse_result.second),
+ − 1153 std::move(com))
+ − 1154 {}
+ − 1155
+ − 1156 // type checking and casting ============================================
+ − 1157
+ − 1158 template<typename T, typename std::enable_if<
+ − 1159 detail::is_exact_toml_type<T, value_type>::value,
+ − 1160 std::nullptr_t>::type = nullptr>
+ − 1161 bool is() const noexcept
+ − 1162 {
+ − 1163 return detail::type_to_enum<T, value_type>::value == this->type_;
+ − 1164 }
+ − 1165 bool is(value_t t) const noexcept {return t == this->type_;}
+ − 1166
+ − 1167 bool is_uninitialized() const noexcept {return this->is(value_t::empty );}
+ − 1168 bool is_boolean() const noexcept {return this->is(value_t::boolean );}
+ − 1169 bool is_integer() const noexcept {return this->is(value_t::integer );}
+ − 1170 bool is_floating() const noexcept {return this->is(value_t::floating );}
+ − 1171 bool is_string() const noexcept {return this->is(value_t::string );}
+ − 1172 bool is_offset_datetime() const noexcept {return this->is(value_t::offset_datetime);}
+ − 1173 bool is_local_datetime() const noexcept {return this->is(value_t::local_datetime );}
+ − 1174 bool is_local_date() const noexcept {return this->is(value_t::local_date );}
+ − 1175 bool is_local_time() const noexcept {return this->is(value_t::local_time );}
+ − 1176 bool is_array() const noexcept {return this->is(value_t::array );}
+ − 1177 bool is_table() const noexcept {return this->is(value_t::table );}
+ − 1178
+ − 1179 value_t type() const noexcept {return type_;}
+ − 1180
+ − 1181 template<value_t T>
+ − 1182 typename detail::enum_to_type<T, value_type>::type& cast() &
+ − 1183 {
+ − 1184 if(this->type_ != T)
+ − 1185 {
+ − 1186 detail::throw_bad_cast<T>("toml::value::cast: ", this->type_, *this);
+ − 1187 }
+ − 1188 return detail::switch_cast<T>::invoke(*this);
+ − 1189 }
+ − 1190 template<value_t T>
+ − 1191 typename detail::enum_to_type<T, value_type>::type const& cast() const&
+ − 1192 {
+ − 1193 if(this->type_ != T)
+ − 1194 {
+ − 1195 detail::throw_bad_cast<T>("toml::value::cast: ", this->type_, *this);
+ − 1196 }
+ − 1197 return detail::switch_cast<T>::invoke(*this);
+ − 1198 }
+ − 1199 template<value_t T>
+ − 1200 typename detail::enum_to_type<T, value_type>::type&& cast() &&
+ − 1201 {
+ − 1202 if(this->type_ != T)
+ − 1203 {
+ − 1204 detail::throw_bad_cast<T>("toml::value::cast: ", this->type_, *this);
+ − 1205 }
+ − 1206 return detail::switch_cast<T>::invoke(std::move(*this));
+ − 1207 }
+ − 1208
+ − 1209 // ------------------------------------------------------------------------
+ − 1210 // nothrow version
+ − 1211
+ − 1212 boolean const& as_boolean (const std::nothrow_t&) const& noexcept {return this->boolean_;}
+ − 1213 integer const& as_integer (const std::nothrow_t&) const& noexcept {return this->integer_;}
+ − 1214 floating const& as_floating (const std::nothrow_t&) const& noexcept {return this->floating_;}
+ − 1215 string const& as_string (const std::nothrow_t&) const& noexcept {return this->string_;}
+ − 1216 offset_datetime const& as_offset_datetime(const std::nothrow_t&) const& noexcept {return this->offset_datetime_;}
+ − 1217 local_datetime const& as_local_datetime (const std::nothrow_t&) const& noexcept {return this->local_datetime_;}
+ − 1218 local_date const& as_local_date (const std::nothrow_t&) const& noexcept {return this->local_date_;}
+ − 1219 local_time const& as_local_time (const std::nothrow_t&) const& noexcept {return this->local_time_;}
+ − 1220 array_type const& as_array (const std::nothrow_t&) const& noexcept {return this->array_.value();}
+ − 1221 table_type const& as_table (const std::nothrow_t&) const& noexcept {return this->table_.value();}
+ − 1222
+ − 1223 boolean & as_boolean (const std::nothrow_t&) & noexcept {return this->boolean_;}
+ − 1224 integer & as_integer (const std::nothrow_t&) & noexcept {return this->integer_;}
+ − 1225 floating & as_floating (const std::nothrow_t&) & noexcept {return this->floating_;}
+ − 1226 string & as_string (const std::nothrow_t&) & noexcept {return this->string_;}
+ − 1227 offset_datetime& as_offset_datetime(const std::nothrow_t&) & noexcept {return this->offset_datetime_;}
+ − 1228 local_datetime & as_local_datetime (const std::nothrow_t&) & noexcept {return this->local_datetime_;}
+ − 1229 local_date & as_local_date (const std::nothrow_t&) & noexcept {return this->local_date_;}
+ − 1230 local_time & as_local_time (const std::nothrow_t&) & noexcept {return this->local_time_;}
+ − 1231 array_type & as_array (const std::nothrow_t&) & noexcept {return this->array_.value();}
+ − 1232 table_type & as_table (const std::nothrow_t&) & noexcept {return this->table_.value();}
+ − 1233
+ − 1234 boolean && as_boolean (const std::nothrow_t&) && noexcept {return std::move(this->boolean_);}
+ − 1235 integer && as_integer (const std::nothrow_t&) && noexcept {return std::move(this->integer_);}
+ − 1236 floating && as_floating (const std::nothrow_t&) && noexcept {return std::move(this->floating_);}
+ − 1237 string && as_string (const std::nothrow_t&) && noexcept {return std::move(this->string_);}
+ − 1238 offset_datetime&& as_offset_datetime(const std::nothrow_t&) && noexcept {return std::move(this->offset_datetime_);}
+ − 1239 local_datetime && as_local_datetime (const std::nothrow_t&) && noexcept {return std::move(this->local_datetime_);}
+ − 1240 local_date && as_local_date (const std::nothrow_t&) && noexcept {return std::move(this->local_date_);}
+ − 1241 local_time && as_local_time (const std::nothrow_t&) && noexcept {return std::move(this->local_time_);}
+ − 1242 array_type && as_array (const std::nothrow_t&) && noexcept {return std::move(this->array_.value());}
+ − 1243 table_type && as_table (const std::nothrow_t&) && noexcept {return std::move(this->table_.value());}
+ − 1244
+ − 1245 // ========================================================================
+ − 1246 // throw version
+ − 1247 // ------------------------------------------------------------------------
+ − 1248 // const reference {{{
+ − 1249
+ − 1250 boolean const& as_boolean() const&
+ − 1251 {
+ − 1252 if(this->type_ != value_t::boolean)
+ − 1253 {
+ − 1254 detail::throw_bad_cast<value_t::boolean>(
+ − 1255 "toml::value::as_boolean(): ", this->type_, *this);
+ − 1256 }
+ − 1257 return this->boolean_;
+ − 1258 }
+ − 1259 integer const& as_integer() const&
+ − 1260 {
+ − 1261 if(this->type_ != value_t::integer)
+ − 1262 {
+ − 1263 detail::throw_bad_cast<value_t::integer>(
+ − 1264 "toml::value::as_integer(): ", this->type_, *this);
+ − 1265 }
+ − 1266 return this->integer_;
+ − 1267 }
+ − 1268 floating const& as_floating() const&
+ − 1269 {
+ − 1270 if(this->type_ != value_t::floating)
+ − 1271 {
+ − 1272 detail::throw_bad_cast<value_t::floating>(
+ − 1273 "toml::value::as_floating(): ", this->type_, *this);
+ − 1274 }
+ − 1275 return this->floating_;
+ − 1276 }
+ − 1277 string const& as_string() const&
+ − 1278 {
+ − 1279 if(this->type_ != value_t::string)
+ − 1280 {
+ − 1281 detail::throw_bad_cast<value_t::string>(
+ − 1282 "toml::value::as_string(): ", this->type_, *this);
+ − 1283 }
+ − 1284 return this->string_;
+ − 1285 }
+ − 1286 offset_datetime const& as_offset_datetime() const&
+ − 1287 {
+ − 1288 if(this->type_ != value_t::offset_datetime)
+ − 1289 {
+ − 1290 detail::throw_bad_cast<value_t::offset_datetime>(
+ − 1291 "toml::value::as_offset_datetime(): ", this->type_, *this);
+ − 1292 }
+ − 1293 return this->offset_datetime_;
+ − 1294 }
+ − 1295 local_datetime const& as_local_datetime() const&
+ − 1296 {
+ − 1297 if(this->type_ != value_t::local_datetime)
+ − 1298 {
+ − 1299 detail::throw_bad_cast<value_t::local_datetime>(
+ − 1300 "toml::value::as_local_datetime(): ", this->type_, *this);
+ − 1301 }
+ − 1302 return this->local_datetime_;
+ − 1303 }
+ − 1304 local_date const& as_local_date() const&
+ − 1305 {
+ − 1306 if(this->type_ != value_t::local_date)
+ − 1307 {
+ − 1308 detail::throw_bad_cast<value_t::local_date>(
+ − 1309 "toml::value::as_local_date(): ", this->type_, *this);
+ − 1310 }
+ − 1311 return this->local_date_;
+ − 1312 }
+ − 1313 local_time const& as_local_time() const&
+ − 1314 {
+ − 1315 if(this->type_ != value_t::local_time)
+ − 1316 {
+ − 1317 detail::throw_bad_cast<value_t::local_time>(
+ − 1318 "toml::value::as_local_time(): ", this->type_, *this);
+ − 1319 }
+ − 1320 return this->local_time_;
+ − 1321 }
+ − 1322 array_type const& as_array() const&
+ − 1323 {
+ − 1324 if(this->type_ != value_t::array)
+ − 1325 {
+ − 1326 detail::throw_bad_cast<value_t::array>(
+ − 1327 "toml::value::as_array(): ", this->type_, *this);
+ − 1328 }
+ − 1329 return this->array_.value();
+ − 1330 }
+ − 1331 table_type const& as_table() const&
+ − 1332 {
+ − 1333 if(this->type_ != value_t::table)
+ − 1334 {
+ − 1335 detail::throw_bad_cast<value_t::table>(
+ − 1336 "toml::value::as_table(): ", this->type_, *this);
+ − 1337 }
+ − 1338 return this->table_.value();
+ − 1339 }
+ − 1340 // }}}
+ − 1341 // ------------------------------------------------------------------------
+ − 1342 // nonconst reference {{{
+ − 1343
+ − 1344 boolean & as_boolean() &
+ − 1345 {
+ − 1346 if(this->type_ != value_t::boolean)
+ − 1347 {
+ − 1348 detail::throw_bad_cast<value_t::boolean>(
+ − 1349 "toml::value::as_boolean(): ", this->type_, *this);
+ − 1350 }
+ − 1351 return this->boolean_;
+ − 1352 }
+ − 1353 integer & as_integer() &
+ − 1354 {
+ − 1355 if(this->type_ != value_t::integer)
+ − 1356 {
+ − 1357 detail::throw_bad_cast<value_t::integer>(
+ − 1358 "toml::value::as_integer(): ", this->type_, *this);
+ − 1359 }
+ − 1360 return this->integer_;
+ − 1361 }
+ − 1362 floating & as_floating() &
+ − 1363 {
+ − 1364 if(this->type_ != value_t::floating)
+ − 1365 {
+ − 1366 detail::throw_bad_cast<value_t::floating>(
+ − 1367 "toml::value::as_floating(): ", this->type_, *this);
+ − 1368 }
+ − 1369 return this->floating_;
+ − 1370 }
+ − 1371 string & as_string() &
+ − 1372 {
+ − 1373 if(this->type_ != value_t::string)
+ − 1374 {
+ − 1375 detail::throw_bad_cast<value_t::string>(
+ − 1376 "toml::value::as_string(): ", this->type_, *this);
+ − 1377 }
+ − 1378 return this->string_;
+ − 1379 }
+ − 1380 offset_datetime & as_offset_datetime() &
+ − 1381 {
+ − 1382 if(this->type_ != value_t::offset_datetime)
+ − 1383 {
+ − 1384 detail::throw_bad_cast<value_t::offset_datetime>(
+ − 1385 "toml::value::as_offset_datetime(): ", this->type_, *this);
+ − 1386 }
+ − 1387 return this->offset_datetime_;
+ − 1388 }
+ − 1389 local_datetime & as_local_datetime() &
+ − 1390 {
+ − 1391 if(this->type_ != value_t::local_datetime)
+ − 1392 {
+ − 1393 detail::throw_bad_cast<value_t::local_datetime>(
+ − 1394 "toml::value::as_local_datetime(): ", this->type_, *this);
+ − 1395 }
+ − 1396 return this->local_datetime_;
+ − 1397 }
+ − 1398 local_date & as_local_date() &
+ − 1399 {
+ − 1400 if(this->type_ != value_t::local_date)
+ − 1401 {
+ − 1402 detail::throw_bad_cast<value_t::local_date>(
+ − 1403 "toml::value::as_local_date(): ", this->type_, *this);
+ − 1404 }
+ − 1405 return this->local_date_;
+ − 1406 }
+ − 1407 local_time & as_local_time() &
+ − 1408 {
+ − 1409 if(this->type_ != value_t::local_time)
+ − 1410 {
+ − 1411 detail::throw_bad_cast<value_t::local_time>(
+ − 1412 "toml::value::as_local_time(): ", this->type_, *this);
+ − 1413 }
+ − 1414 return this->local_time_;
+ − 1415 }
+ − 1416 array_type & as_array() &
+ − 1417 {
+ − 1418 if(this->type_ != value_t::array)
+ − 1419 {
+ − 1420 detail::throw_bad_cast<value_t::array>(
+ − 1421 "toml::value::as_array(): ", this->type_, *this);
+ − 1422 }
+ − 1423 return this->array_.value();
+ − 1424 }
+ − 1425 table_type & as_table() &
+ − 1426 {
+ − 1427 if(this->type_ != value_t::table)
+ − 1428 {
+ − 1429 detail::throw_bad_cast<value_t::table>(
+ − 1430 "toml::value::as_table(): ", this->type_, *this);
+ − 1431 }
+ − 1432 return this->table_.value();
+ − 1433 }
+ − 1434
+ − 1435 // }}}
+ − 1436 // ------------------------------------------------------------------------
+ − 1437 // rvalue reference {{{
+ − 1438
+ − 1439 boolean && as_boolean() &&
+ − 1440 {
+ − 1441 if(this->type_ != value_t::boolean)
+ − 1442 {
+ − 1443 detail::throw_bad_cast<value_t::boolean>(
+ − 1444 "toml::value::as_boolean(): ", this->type_, *this);
+ − 1445 }
+ − 1446 return std::move(this->boolean_);
+ − 1447 }
+ − 1448 integer && as_integer() &&
+ − 1449 {
+ − 1450 if(this->type_ != value_t::integer)
+ − 1451 {
+ − 1452 detail::throw_bad_cast<value_t::integer>(
+ − 1453 "toml::value::as_integer(): ", this->type_, *this);
+ − 1454 }
+ − 1455 return std::move(this->integer_);
+ − 1456 }
+ − 1457 floating && as_floating() &&
+ − 1458 {
+ − 1459 if(this->type_ != value_t::floating)
+ − 1460 {
+ − 1461 detail::throw_bad_cast<value_t::floating>(
+ − 1462 "toml::value::as_floating(): ", this->type_, *this);
+ − 1463 }
+ − 1464 return std::move(this->floating_);
+ − 1465 }
+ − 1466 string && as_string() &&
+ − 1467 {
+ − 1468 if(this->type_ != value_t::string)
+ − 1469 {
+ − 1470 detail::throw_bad_cast<value_t::string>(
+ − 1471 "toml::value::as_string(): ", this->type_, *this);
+ − 1472 }
+ − 1473 return std::move(this->string_);
+ − 1474 }
+ − 1475 offset_datetime && as_offset_datetime() &&
+ − 1476 {
+ − 1477 if(this->type_ != value_t::offset_datetime)
+ − 1478 {
+ − 1479 detail::throw_bad_cast<value_t::offset_datetime>(
+ − 1480 "toml::value::as_offset_datetime(): ", this->type_, *this);
+ − 1481 }
+ − 1482 return std::move(this->offset_datetime_);
+ − 1483 }
+ − 1484 local_datetime && as_local_datetime() &&
+ − 1485 {
+ − 1486 if(this->type_ != value_t::local_datetime)
+ − 1487 {
+ − 1488 detail::throw_bad_cast<value_t::local_datetime>(
+ − 1489 "toml::value::as_local_datetime(): ", this->type_, *this);
+ − 1490 }
+ − 1491 return std::move(this->local_datetime_);
+ − 1492 }
+ − 1493 local_date && as_local_date() &&
+ − 1494 {
+ − 1495 if(this->type_ != value_t::local_date)
+ − 1496 {
+ − 1497 detail::throw_bad_cast<value_t::local_date>(
+ − 1498 "toml::value::as_local_date(): ", this->type_, *this);
+ − 1499 }
+ − 1500 return std::move(this->local_date_);
+ − 1501 }
+ − 1502 local_time && as_local_time() &&
+ − 1503 {
+ − 1504 if(this->type_ != value_t::local_time)
+ − 1505 {
+ − 1506 detail::throw_bad_cast<value_t::local_time>(
+ − 1507 "toml::value::as_local_time(): ", this->type_, *this);
+ − 1508 }
+ − 1509 return std::move(this->local_time_);
+ − 1510 }
+ − 1511 array_type && as_array() &&
+ − 1512 {
+ − 1513 if(this->type_ != value_t::array)
+ − 1514 {
+ − 1515 detail::throw_bad_cast<value_t::array>(
+ − 1516 "toml::value::as_array(): ", this->type_, *this);
+ − 1517 }
+ − 1518 return std::move(this->array_.value());
+ − 1519 }
+ − 1520 table_type && as_table() &&
+ − 1521 {
+ − 1522 if(this->type_ != value_t::table)
+ − 1523 {
+ − 1524 detail::throw_bad_cast<value_t::table>(
+ − 1525 "toml::value::as_table(): ", this->type_, *this);
+ − 1526 }
+ − 1527 return std::move(this->table_.value());
+ − 1528 }
+ − 1529 // }}}
+ − 1530
+ − 1531 // accessors =============================================================
+ − 1532 //
+ − 1533 // may throw type_error or out_of_range
+ − 1534 //
+ − 1535 value_type& at(const key& k)
+ − 1536 {
+ − 1537 if(!this->is_table())
+ − 1538 {
+ − 1539 detail::throw_bad_cast<value_t::table>(
+ − 1540 "toml::value::at(key): ", this->type_, *this);
+ − 1541 }
+ − 1542 if(this->as_table(std::nothrow).count(k) == 0)
+ − 1543 {
+ − 1544 detail::throw_key_not_found_error(*this, k);
+ − 1545 }
+ − 1546 return this->as_table(std::nothrow).at(k);
+ − 1547 }
+ − 1548 value_type const& at(const key& k) const
+ − 1549 {
+ − 1550 if(!this->is_table())
+ − 1551 {
+ − 1552 detail::throw_bad_cast<value_t::table>(
+ − 1553 "toml::value::at(key): ", this->type_, *this);
+ − 1554 }
+ − 1555 if(this->as_table(std::nothrow).count(k) == 0)
+ − 1556 {
+ − 1557 detail::throw_key_not_found_error(*this, k);
+ − 1558 }
+ − 1559 return this->as_table(std::nothrow).at(k);
+ − 1560 }
+ − 1561 value_type& operator[](const key& k)
+ − 1562 {
+ − 1563 if(this->is_uninitialized())
+ − 1564 {
+ − 1565 *this = table_type{};
+ − 1566 }
+ − 1567 else if(!this->is_table()) // initialized, but not a table
+ − 1568 {
+ − 1569 detail::throw_bad_cast<value_t::table>(
+ − 1570 "toml::value::operator[](key): ", this->type_, *this);
+ − 1571 }
+ − 1572 return this->as_table(std::nothrow)[k];
+ − 1573 }
+ − 1574
+ − 1575 value_type& at(const std::size_t idx)
+ − 1576 {
+ − 1577 if(!this->is_array())
+ − 1578 {
+ − 1579 detail::throw_bad_cast<value_t::array>(
+ − 1580 "toml::value::at(idx): ", this->type_, *this);
+ − 1581 }
+ − 1582 if(this->as_array(std::nothrow).size() <= idx)
+ − 1583 {
+ − 1584 throw std::out_of_range(detail::format_underline(
+ − 1585 "toml::value::at(idx): no element corresponding to the index", {
+ − 1586 {this->location(), concat_to_string("the length is ",
+ − 1587 this->as_array(std::nothrow).size(),
+ − 1588 ", and the specified index is ", idx)}
+ − 1589 }));
+ − 1590 }
+ − 1591 return this->as_array().at(idx);
+ − 1592 }
+ − 1593 value_type const& at(const std::size_t idx) const
+ − 1594 {
+ − 1595 if(!this->is_array())
+ − 1596 {
+ − 1597 detail::throw_bad_cast<value_t::array>(
+ − 1598 "toml::value::at(idx): ", this->type_, *this);
+ − 1599 }
+ − 1600 if(this->as_array(std::nothrow).size() <= idx)
+ − 1601 {
+ − 1602 throw std::out_of_range(detail::format_underline(
+ − 1603 "toml::value::at(idx): no element corresponding to the index", {
+ − 1604 {this->location(), concat_to_string("the length is ",
+ − 1605 this->as_array(std::nothrow).size(),
+ − 1606 ", and the specified index is ", idx)}
+ − 1607 }));
+ − 1608 }
+ − 1609 return this->as_array(std::nothrow).at(idx);
+ − 1610 }
+ − 1611
+ − 1612 value_type& operator[](const std::size_t idx) noexcept
+ − 1613 {
+ − 1614 // no check...
+ − 1615 return this->as_array(std::nothrow)[idx];
+ − 1616 }
+ − 1617 value_type const& operator[](const std::size_t idx) const noexcept
+ − 1618 {
+ − 1619 // no check...
+ − 1620 return this->as_array(std::nothrow)[idx];
+ − 1621 }
+ − 1622
+ − 1623 void push_back(const value_type& x)
+ − 1624 {
+ − 1625 if(!this->is_array())
+ − 1626 {
+ − 1627 detail::throw_bad_cast<value_t::array>(
+ − 1628 "toml::value::push_back(value): ", this->type_, *this);
+ − 1629 }
+ − 1630 this->as_array(std::nothrow).push_back(x);
+ − 1631 return;
+ − 1632 }
+ − 1633 void push_back(value_type&& x)
+ − 1634 {
+ − 1635 if(!this->is_array())
+ − 1636 {
+ − 1637 detail::throw_bad_cast<value_t::array>(
+ − 1638 "toml::value::push_back(value): ", this->type_, *this);
+ − 1639 }
+ − 1640 this->as_array(std::nothrow).push_back(std::move(x));
+ − 1641 return;
+ − 1642 }
+ − 1643
+ − 1644 template<typename ... Ts>
+ − 1645 value_type& emplace_back(Ts&& ... args)
+ − 1646 {
+ − 1647 if(!this->is_array())
+ − 1648 {
+ − 1649 detail::throw_bad_cast<value_t::array>(
+ − 1650 "toml::value::emplace_back(...): ", this->type_, *this);
+ − 1651 }
+ − 1652 this->as_array(std::nothrow).emplace_back(std::forward<Ts>(args) ...);
+ − 1653 return this->as_array(std::nothrow).back();
+ − 1654 }
+ − 1655
+ − 1656 std::size_t size() const
+ − 1657 {
+ − 1658 switch(this->type_)
+ − 1659 {
+ − 1660 case value_t::array:
+ − 1661 {
+ − 1662 return this->as_array(std::nothrow).size();
+ − 1663 }
+ − 1664 case value_t::table:
+ − 1665 {
+ − 1666 return this->as_table(std::nothrow).size();
+ − 1667 }
+ − 1668 case value_t::string:
+ − 1669 {
+ − 1670 return this->as_string(std::nothrow).str.size();
+ − 1671 }
+ − 1672 default:
+ − 1673 {
+ − 1674 throw type_error(detail::format_underline(
+ − 1675 "toml::value::size(): bad_cast to container types", {
+ − 1676 {this->location(),
+ − 1677 concat_to_string("the actual type is ", this->type_)}
+ − 1678 }), this->location());
+ − 1679 }
+ − 1680 }
+ − 1681 }
+ − 1682
+ − 1683 std::size_t count(const key_type& k) const
+ − 1684 {
+ − 1685 if(!this->is_table())
+ − 1686 {
+ − 1687 detail::throw_bad_cast<value_t::table>(
+ − 1688 "toml::value::count(key): ", this->type_, *this);
+ − 1689 }
+ − 1690 return this->as_table(std::nothrow).count(k);
+ − 1691 }
+ − 1692
+ − 1693 bool contains(const key_type& k) const
+ − 1694 {
+ − 1695 if(!this->is_table())
+ − 1696 {
+ − 1697 detail::throw_bad_cast<value_t::table>(
+ − 1698 "toml::value::contains(key): ", this->type_, *this);
+ − 1699 }
+ − 1700 return (this->as_table(std::nothrow).count(k) != 0);
+ − 1701 }
+ − 1702
+ − 1703 source_location location() const
+ − 1704 {
+ − 1705 return source_location(this->region_info_.get());
+ − 1706 }
+ − 1707
+ − 1708 comment_type const& comments() const noexcept {return this->comments_;}
+ − 1709 comment_type& comments() noexcept {return this->comments_;}
+ − 1710
+ − 1711 private:
+ − 1712
+ − 1713 void cleanup() noexcept
+ − 1714 {
+ − 1715 switch(this->type_)
+ − 1716 {
+ − 1717 case value_t::string : {string_.~string(); return;}
+ − 1718 case value_t::array : {array_.~array_storage(); return;}
+ − 1719 case value_t::table : {table_.~table_storage(); return;}
+ − 1720 default : return;
+ − 1721 }
+ − 1722 }
+ − 1723
+ − 1724 // for error messages
+ − 1725 template<typename Value>
+ − 1726 friend region_base const* detail::get_region(const Value& v);
+ − 1727
+ − 1728 template<typename Value>
+ − 1729 friend void detail::change_region(Value& v, detail::region reg);
+ − 1730
+ − 1731 private:
+ − 1732
+ − 1733 using array_storage = detail::storage<array_type>;
+ − 1734 using table_storage = detail::storage<table_type>;
+ − 1735
+ − 1736 value_t type_;
+ − 1737 union
+ − 1738 {
+ − 1739 boolean boolean_;
+ − 1740 integer integer_;
+ − 1741 floating floating_;
+ − 1742 string string_;
+ − 1743 offset_datetime offset_datetime_;
+ − 1744 local_datetime local_datetime_;
+ − 1745 local_date local_date_;
+ − 1746 local_time local_time_;
+ − 1747 array_storage array_;
+ − 1748 table_storage table_;
+ − 1749 };
+ − 1750 std::shared_ptr<region_base> region_info_;
+ − 1751 comment_type comments_;
+ − 1752 };
+ − 1753
+ − 1754 // default toml::value and default array/table.
+ − 1755 // TOML11_DEFAULT_COMMENT_STRATEGY is defined in comments.hpp
+ − 1756 using value = basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>;
+ − 1757 using array = typename value::array_type;
+ − 1758 using table = typename value::table_type;
+ − 1759
+ − 1760 template<typename C, template<typename ...> class T, template<typename ...> class A>
+ − 1761 inline bool
+ − 1762 operator==(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+ − 1763 {
+ − 1764 if(lhs.type() != rhs.type()) {return false;}
+ − 1765 if(lhs.comments() != rhs.comments()) {return false;}
+ − 1766
+ − 1767 switch(lhs.type())
+ − 1768 {
+ − 1769 case value_t::boolean :
+ − 1770 {
+ − 1771 return lhs.as_boolean() == rhs.as_boolean();
+ − 1772 }
+ − 1773 case value_t::integer :
+ − 1774 {
+ − 1775 return lhs.as_integer() == rhs.as_integer();
+ − 1776 }
+ − 1777 case value_t::floating :
+ − 1778 {
+ − 1779 return lhs.as_floating() == rhs.as_floating();
+ − 1780 }
+ − 1781 case value_t::string :
+ − 1782 {
+ − 1783 return lhs.as_string() == rhs.as_string();
+ − 1784 }
+ − 1785 case value_t::offset_datetime:
+ − 1786 {
+ − 1787 return lhs.as_offset_datetime() == rhs.as_offset_datetime();
+ − 1788 }
+ − 1789 case value_t::local_datetime:
+ − 1790 {
+ − 1791 return lhs.as_local_datetime() == rhs.as_local_datetime();
+ − 1792 }
+ − 1793 case value_t::local_date:
+ − 1794 {
+ − 1795 return lhs.as_local_date() == rhs.as_local_date();
+ − 1796 }
+ − 1797 case value_t::local_time:
+ − 1798 {
+ − 1799 return lhs.as_local_time() == rhs.as_local_time();
+ − 1800 }
+ − 1801 case value_t::array :
+ − 1802 {
+ − 1803 return lhs.as_array() == rhs.as_array();
+ − 1804 }
+ − 1805 case value_t::table :
+ − 1806 {
+ − 1807 return lhs.as_table() == rhs.as_table();
+ − 1808 }
+ − 1809 case value_t::empty : {return true; }
+ − 1810 default: {return false;}
+ − 1811 }
+ − 1812 }
+ − 1813
+ − 1814 template<typename C, template<typename ...> class T, template<typename ...> class A>
+ − 1815 inline bool operator!=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+ − 1816 {
+ − 1817 return !(lhs == rhs);
+ − 1818 }
+ − 1819
+ − 1820 template<typename C, template<typename ...> class T, template<typename ...> class A>
+ − 1821 typename std::enable_if<detail::conjunction<
+ − 1822 detail::is_comparable<typename basic_value<C, T, A>::array_type>,
+ − 1823 detail::is_comparable<typename basic_value<C, T, A>::table_type>
+ − 1824 >::value, bool>::type
+ − 1825 operator<(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+ − 1826 {
+ − 1827 if(lhs.type() != rhs.type()){return (lhs.type() < rhs.type());}
+ − 1828 switch(lhs.type())
+ − 1829 {
+ − 1830 case value_t::boolean :
+ − 1831 {
+ − 1832 return lhs.as_boolean() < rhs.as_boolean() ||
+ − 1833 (lhs.as_boolean() == rhs.as_boolean() &&
+ − 1834 lhs.comments() < rhs.comments());
+ − 1835 }
+ − 1836 case value_t::integer :
+ − 1837 {
+ − 1838 return lhs.as_integer() < rhs.as_integer() ||
+ − 1839 (lhs.as_integer() == rhs.as_integer() &&
+ − 1840 lhs.comments() < rhs.comments());
+ − 1841 }
+ − 1842 case value_t::floating :
+ − 1843 {
+ − 1844 return lhs.as_floating() < rhs.as_floating() ||
+ − 1845 (lhs.as_floating() == rhs.as_floating() &&
+ − 1846 lhs.comments() < rhs.comments());
+ − 1847 }
+ − 1848 case value_t::string :
+ − 1849 {
+ − 1850 return lhs.as_string() < rhs.as_string() ||
+ − 1851 (lhs.as_string() == rhs.as_string() &&
+ − 1852 lhs.comments() < rhs.comments());
+ − 1853 }
+ − 1854 case value_t::offset_datetime:
+ − 1855 {
+ − 1856 return lhs.as_offset_datetime() < rhs.as_offset_datetime() ||
+ − 1857 (lhs.as_offset_datetime() == rhs.as_offset_datetime() &&
+ − 1858 lhs.comments() < rhs.comments());
+ − 1859 }
+ − 1860 case value_t::local_datetime:
+ − 1861 {
+ − 1862 return lhs.as_local_datetime() < rhs.as_local_datetime() ||
+ − 1863 (lhs.as_local_datetime() == rhs.as_local_datetime() &&
+ − 1864 lhs.comments() < rhs.comments());
+ − 1865 }
+ − 1866 case value_t::local_date:
+ − 1867 {
+ − 1868 return lhs.as_local_date() < rhs.as_local_date() ||
+ − 1869 (lhs.as_local_date() == rhs.as_local_date() &&
+ − 1870 lhs.comments() < rhs.comments());
+ − 1871 }
+ − 1872 case value_t::local_time:
+ − 1873 {
+ − 1874 return lhs.as_local_time() < rhs.as_local_time() ||
+ − 1875 (lhs.as_local_time() == rhs.as_local_time() &&
+ − 1876 lhs.comments() < rhs.comments());
+ − 1877 }
+ − 1878 case value_t::array :
+ − 1879 {
+ − 1880 return lhs.as_array() < rhs.as_array() ||
+ − 1881 (lhs.as_array() == rhs.as_array() &&
+ − 1882 lhs.comments() < rhs.comments());
+ − 1883 }
+ − 1884 case value_t::table :
+ − 1885 {
+ − 1886 return lhs.as_table() < rhs.as_table() ||
+ − 1887 (lhs.as_table() == rhs.as_table() &&
+ − 1888 lhs.comments() < rhs.comments());
+ − 1889 }
+ − 1890 case value_t::empty :
+ − 1891 {
+ − 1892 return lhs.comments() < rhs.comments();
+ − 1893 }
+ − 1894 default:
+ − 1895 {
+ − 1896 return lhs.comments() < rhs.comments();
+ − 1897 }
+ − 1898 }
+ − 1899 }
+ − 1900
+ − 1901 template<typename C, template<typename ...> class T, template<typename ...> class A>
+ − 1902 typename std::enable_if<detail::conjunction<
+ − 1903 detail::is_comparable<typename basic_value<C, T, A>::array_type>,
+ − 1904 detail::is_comparable<typename basic_value<C, T, A>::table_type>
+ − 1905 >::value, bool>::type
+ − 1906 operator<=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+ − 1907 {
+ − 1908 return (lhs < rhs) || (lhs == rhs);
+ − 1909 }
+ − 1910 template<typename C, template<typename ...> class T, template<typename ...> class A>
+ − 1911 typename std::enable_if<detail::conjunction<
+ − 1912 detail::is_comparable<typename basic_value<C, T, A>::array_type>,
+ − 1913 detail::is_comparable<typename basic_value<C, T, A>::table_type>
+ − 1914 >::value, bool>::type
+ − 1915 operator>(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+ − 1916 {
+ − 1917 return !(lhs <= rhs);
+ − 1918 }
+ − 1919 template<typename C, template<typename ...> class T, template<typename ...> class A>
+ − 1920 typename std::enable_if<detail::conjunction<
+ − 1921 detail::is_comparable<typename basic_value<C, T, A>::array_type>,
+ − 1922 detail::is_comparable<typename basic_value<C, T, A>::table_type>
+ − 1923 >::value, bool>::type
+ − 1924 operator>=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+ − 1925 {
+ − 1926 return !(lhs < rhs);
+ − 1927 }
+ − 1928
+ − 1929 template<typename C, template<typename ...> class T, template<typename ...> class A>
+ − 1930 inline std::string format_error(const std::string& err_msg,
+ − 1931 const basic_value<C, T, A>& v, const std::string& comment,
+ − 1932 std::vector<std::string> hints = {},
+ − 1933 const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
+ − 1934 {
+ − 1935 return detail::format_underline(err_msg, {{v.location(), comment}},
+ − 1936 std::move(hints), colorize);
+ − 1937 }
+ − 1938
+ − 1939 template<typename C, template<typename ...> class T, template<typename ...> class A>
+ − 1940 inline std::string format_error(const std::string& err_msg,
+ − 1941 const toml::basic_value<C, T, A>& v1, const std::string& comment1,
+ − 1942 const toml::basic_value<C, T, A>& v2, const std::string& comment2,
+ − 1943 std::vector<std::string> hints = {},
+ − 1944 const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
+ − 1945 {
+ − 1946 return detail::format_underline(err_msg, {
+ − 1947 {v1.location(), comment1}, {v2.location(), comment2}
+ − 1948 }, std::move(hints), colorize);
+ − 1949 }
+ − 1950
+ − 1951 template<typename C, template<typename ...> class T, template<typename ...> class A>
+ − 1952 inline std::string format_error(const std::string& err_msg,
+ − 1953 const toml::basic_value<C, T, A>& v1, const std::string& comment1,
+ − 1954 const toml::basic_value<C, T, A>& v2, const std::string& comment2,
+ − 1955 const toml::basic_value<C, T, A>& v3, const std::string& comment3,
+ − 1956 std::vector<std::string> hints = {},
+ − 1957 const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
+ − 1958 {
+ − 1959 return detail::format_underline(err_msg, {{v1.location(), comment1},
+ − 1960 {v2.location(), comment2}, {v3.location(), comment3}
+ − 1961 }, std::move(hints), colorize);
+ − 1962 }
+ − 1963
+ − 1964 template<typename Visitor, typename C,
+ − 1965 template<typename ...> class T, template<typename ...> class A>
+ − 1966 detail::return_type_of_t<Visitor, const toml::boolean&>
+ − 1967 visit(Visitor&& visitor, const toml::basic_value<C, T, A>& v)
+ − 1968 {
+ − 1969 switch(v.type())
+ − 1970 {
+ − 1971 case value_t::boolean : {return visitor(v.as_boolean ());}
+ − 1972 case value_t::integer : {return visitor(v.as_integer ());}
+ − 1973 case value_t::floating : {return visitor(v.as_floating ());}
+ − 1974 case value_t::string : {return visitor(v.as_string ());}
+ − 1975 case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
+ − 1976 case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
+ − 1977 case value_t::local_date : {return visitor(v.as_local_date ());}
+ − 1978 case value_t::local_time : {return visitor(v.as_local_time ());}
+ − 1979 case value_t::array : {return visitor(v.as_array ());}
+ − 1980 case value_t::table : {return visitor(v.as_table ());}
+ − 1981 case value_t::empty : break;
+ − 1982 default: break;
+ − 1983 }
+ − 1984 throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
+ − 1985 "does not have any valid basic_value.", v, "here"));
+ − 1986 }
+ − 1987
+ − 1988 template<typename Visitor, typename C,
+ − 1989 template<typename ...> class T, template<typename ...> class A>
+ − 1990 detail::return_type_of_t<Visitor, toml::boolean&>
+ − 1991 visit(Visitor&& visitor, toml::basic_value<C, T, A>& v)
+ − 1992 {
+ − 1993 switch(v.type())
+ − 1994 {
+ − 1995 case value_t::boolean : {return visitor(v.as_boolean ());}
+ − 1996 case value_t::integer : {return visitor(v.as_integer ());}
+ − 1997 case value_t::floating : {return visitor(v.as_floating ());}
+ − 1998 case value_t::string : {return visitor(v.as_string ());}
+ − 1999 case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
+ − 2000 case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
+ − 2001 case value_t::local_date : {return visitor(v.as_local_date ());}
+ − 2002 case value_t::local_time : {return visitor(v.as_local_time ());}
+ − 2003 case value_t::array : {return visitor(v.as_array ());}
+ − 2004 case value_t::table : {return visitor(v.as_table ());}
+ − 2005 case value_t::empty : break;
+ − 2006 default: break;
+ − 2007 }
+ − 2008 throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
+ − 2009 "does not have any valid basic_value.", v, "here"));
+ − 2010 }
+ − 2011
+ − 2012 template<typename Visitor, typename C,
+ − 2013 template<typename ...> class T, template<typename ...> class A>
+ − 2014 detail::return_type_of_t<Visitor, toml::boolean&&>
+ − 2015 visit(Visitor&& visitor, toml::basic_value<C, T, A>&& v)
+ − 2016 {
+ − 2017 switch(v.type())
+ − 2018 {
+ − 2019 case value_t::boolean : {return visitor(std::move(v.as_boolean ()));}
+ − 2020 case value_t::integer : {return visitor(std::move(v.as_integer ()));}
+ − 2021 case value_t::floating : {return visitor(std::move(v.as_floating ()));}
+ − 2022 case value_t::string : {return visitor(std::move(v.as_string ()));}
+ − 2023 case value_t::offset_datetime: {return visitor(std::move(v.as_offset_datetime()));}
+ − 2024 case value_t::local_datetime : {return visitor(std::move(v.as_local_datetime ()));}
+ − 2025 case value_t::local_date : {return visitor(std::move(v.as_local_date ()));}
+ − 2026 case value_t::local_time : {return visitor(std::move(v.as_local_time ()));}
+ − 2027 case value_t::array : {return visitor(std::move(v.as_array ()));}
+ − 2028 case value_t::table : {return visitor(std::move(v.as_table ()));}
+ − 2029 case value_t::empty : break;
+ − 2030 default: break;
+ − 2031 }
+ − 2032 throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
+ − 2033 "does not have any valid basic_value.", v, "here"));
+ − 2034 }
+ − 2035
+ − 2036 }// toml
+ − 2037 #endif// TOML11_VALUE