Mercurial > minori
comparison dep/toml11/toml/get.hpp @ 318:3b355fa948c7
config: use TOML instead of INI
unfortunately, INI is not enough, and causes some paths including
semicolons to break with our current storage of the library folders.
so, I decided to switch to TOML which does support real arrays...
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Wed, 12 Jun 2024 05:25:41 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
317:b1f4d1867ab1 | 318:3b355fa948c7 |
---|---|
1 // Copyright Toru Niina 2017. | |
2 // Distributed under the MIT License. | |
3 #ifndef TOML11_GET_HPP | |
4 #define TOML11_GET_HPP | |
5 #include <algorithm> | |
6 | |
7 #include "from.hpp" | |
8 #include "result.hpp" | |
9 #include "value.hpp" | |
10 | |
11 namespace toml | |
12 { | |
13 | |
14 // ============================================================================ | |
15 // exact toml::* type | |
16 | |
17 template<typename T, typename C, | |
18 template<typename ...> class M, template<typename ...> class V> | |
19 detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> & | |
20 get(basic_value<C, M, V>& v) | |
21 { | |
22 return v.template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>(); | |
23 } | |
24 | |
25 template<typename T, typename C, | |
26 template<typename ...> class M, template<typename ...> class V> | |
27 detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const& | |
28 get(const basic_value<C, M, V>& v) | |
29 { | |
30 return v.template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>(); | |
31 } | |
32 | |
33 template<typename T, typename C, | |
34 template<typename ...> class M, template<typename ...> class V> | |
35 detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> | |
36 get(basic_value<C, M, V>&& v) | |
37 { | |
38 return T(std::move(v).template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>()); | |
39 } | |
40 | |
41 // ============================================================================ | |
42 // T == toml::value; identity transformation. | |
43 | |
44 template<typename T, typename C, | |
45 template<typename ...> class M, template<typename ...> class V> | |
46 inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T>& | |
47 get(basic_value<C, M, V>& v) | |
48 { | |
49 return v; | |
50 } | |
51 | |
52 template<typename T, typename C, | |
53 template<typename ...> class M, template<typename ...> class V> | |
54 inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T> const& | |
55 get(const basic_value<C, M, V>& v) | |
56 { | |
57 return v; | |
58 } | |
59 | |
60 template<typename T, typename C, | |
61 template<typename ...> class M, template<typename ...> class V> | |
62 inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T> | |
63 get(basic_value<C, M, V>&& v) | |
64 { | |
65 return basic_value<C, M, V>(std::move(v)); | |
66 } | |
67 | |
68 // ============================================================================ | |
69 // T == toml::basic_value<C2, M2, V2>; basic_value -> basic_value | |
70 | |
71 template<typename T, typename C, | |
72 template<typename ...> class M, template<typename ...> class V> | |
73 inline detail::enable_if_t<detail::conjunction<detail::is_basic_value<T>, | |
74 detail::negation<std::is_same<T, basic_value<C, M, V>>> | |
75 >::value, T> | |
76 get(const basic_value<C, M, V>& v) | |
77 { | |
78 return T(v); | |
79 } | |
80 | |
81 // ============================================================================ | |
82 // integer convertible from toml::Integer | |
83 | |
84 template<typename T, typename C, | |
85 template<typename ...> class M, template<typename ...> class V> | |
86 inline detail::enable_if_t<detail::conjunction< | |
87 std::is_integral<T>, // T is integral | |
88 detail::negation<std::is_same<T, bool>>, // but not bool | |
89 detail::negation< // but not toml::integer | |
90 detail::is_exact_toml_type<T, basic_value<C, M, V>>> | |
91 >::value, T> | |
92 get(const basic_value<C, M, V>& v) | |
93 { | |
94 return static_cast<T>(v.as_integer()); | |
95 } | |
96 | |
97 // ============================================================================ | |
98 // floating point convertible from toml::Float | |
99 | |
100 template<typename T, typename C, | |
101 template<typename ...> class M, template<typename ...> class V> | |
102 inline detail::enable_if_t<detail::conjunction< | |
103 std::is_floating_point<T>, // T is floating_point | |
104 detail::negation< // but not toml::floating | |
105 detail::is_exact_toml_type<T, basic_value<C, M, V>>> | |
106 >::value, T> | |
107 get(const basic_value<C, M, V>& v) | |
108 { | |
109 return static_cast<T>(v.as_floating()); | |
110 } | |
111 | |
112 // ============================================================================ | |
113 // std::string; toml uses its own toml::string, but it should be convertible to | |
114 // std::string seamlessly | |
115 | |
116 template<typename T, typename C, | |
117 template<typename ...> class M, template<typename ...> class V> | |
118 inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>& | |
119 get(basic_value<C, M, V>& v) | |
120 { | |
121 return v.as_string().str; | |
122 } | |
123 | |
124 template<typename T, typename C, | |
125 template<typename ...> class M, template<typename ...> class V> | |
126 inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const& | |
127 get(const basic_value<C, M, V>& v) | |
128 { | |
129 return v.as_string().str; | |
130 } | |
131 | |
132 template<typename T, typename C, | |
133 template<typename ...> class M, template<typename ...> class V> | |
134 inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string> | |
135 get(basic_value<C, M, V>&& v) | |
136 { | |
137 return std::string(std::move(v.as_string().str)); | |
138 } | |
139 | |
140 // ============================================================================ | |
141 // std::string_view | |
142 | |
143 #if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0 | |
144 template<typename T, typename C, | |
145 template<typename ...> class M, template<typename ...> class V> | |
146 inline detail::enable_if_t<std::is_same<T, std::string_view>::value, std::string_view> | |
147 get(const basic_value<C, M, V>& v) | |
148 { | |
149 return std::string_view(v.as_string().str); | |
150 } | |
151 #endif | |
152 | |
153 // ============================================================================ | |
154 // std::chrono::duration from toml::local_time. | |
155 | |
156 template<typename T, typename C, | |
157 template<typename ...> class M, template<typename ...> class V> | |
158 inline detail::enable_if_t<detail::is_chrono_duration<T>::value, T> | |
159 get(const basic_value<C, M, V>& v) | |
160 { | |
161 return std::chrono::duration_cast<T>( | |
162 std::chrono::nanoseconds(v.as_local_time())); | |
163 } | |
164 | |
165 // ============================================================================ | |
166 // std::chrono::system_clock::time_point from toml::datetime variants | |
167 | |
168 template<typename T, typename C, | |
169 template<typename ...> class M, template<typename ...> class V> | |
170 inline detail::enable_if_t< | |
171 std::is_same<std::chrono::system_clock::time_point, T>::value, T> | |
172 get(const basic_value<C, M, V>& v) | |
173 { | |
174 switch(v.type()) | |
175 { | |
176 case value_t::local_date: | |
177 { | |
178 return std::chrono::system_clock::time_point(v.as_local_date()); | |
179 } | |
180 case value_t::local_datetime: | |
181 { | |
182 return std::chrono::system_clock::time_point(v.as_local_datetime()); | |
183 } | |
184 case value_t::offset_datetime: | |
185 { | |
186 return std::chrono::system_clock::time_point(v.as_offset_datetime()); | |
187 } | |
188 default: | |
189 { | |
190 throw type_error(detail::format_underline("toml::value: " | |
191 "bad_cast to std::chrono::system_clock::time_point", { | |
192 {v.location(), concat_to_string("the actual type is ", v.type())} | |
193 }), v.location()); | |
194 } | |
195 } | |
196 } | |
197 | |
198 // ============================================================================ | |
199 // forward declaration to use this recursively. ignore this and go ahead. | |
200 | |
201 // array-like type with push_back(value) method | |
202 template<typename T, typename C, | |
203 template<typename ...> class M, template<typename ...> class V> | |
204 detail::enable_if_t<detail::conjunction< | |
205 detail::is_container<T>, // T is a container | |
206 detail::has_push_back_method<T>, // T::push_back(value) works | |
207 detail::negation< // but not toml::array | |
208 detail::is_exact_toml_type<T, basic_value<C, M, V>>> | |
209 >::value, T> | |
210 get(const basic_value<C, M, V>&); | |
211 | |
212 // array-like type without push_back(value) method | |
213 template<typename T, typename C, | |
214 template<typename ...> class M, template<typename ...> class V> | |
215 detail::enable_if_t<detail::conjunction< | |
216 detail::is_container<T>, // T is a container | |
217 detail::negation<detail::has_push_back_method<T>>, // w/o push_back(...) | |
218 detail::negation<detail::has_specialized_from<T>>, // T does not have special conversion | |
219 detail::negation< // not toml::array | |
220 detail::is_exact_toml_type<T, basic_value<C, M, V>>> | |
221 >::value, T> | |
222 get(const basic_value<C, M, V>&); | |
223 | |
224 // std::pair<T1, T2> | |
225 template<typename T, typename C, | |
226 template<typename ...> class M, template<typename ...> class V> | |
227 detail::enable_if_t<detail::is_std_pair<T>::value, T> | |
228 get(const basic_value<C, M, V>&); | |
229 | |
230 // std::tuple<T1, T2, ...> | |
231 template<typename T, typename C, | |
232 template<typename ...> class M, template<typename ...> class V> | |
233 detail::enable_if_t<detail::is_std_tuple<T>::value, T> | |
234 get(const basic_value<C, M, V>&); | |
235 | |
236 // map-like classes | |
237 template<typename T, typename C, | |
238 template<typename ...> class M, template<typename ...> class V> | |
239 detail::enable_if_t<detail::conjunction< | |
240 detail::is_map<T>, // T is map | |
241 detail::negation< // but not toml::table | |
242 detail::is_exact_toml_type<T, basic_value<C, M, V>>> | |
243 >::value, T> | |
244 get(const basic_value<C, M, V>&); | |
245 | |
246 // T.from_toml(v) | |
247 template<typename T, typename C, | |
248 template<typename ...> class M, template<typename ...> class V> | |
249 detail::enable_if_t<detail::conjunction< | |
250 detail::negation< // not a toml::* type | |
251 detail::is_exact_toml_type<T, basic_value<C, M, V>>>, | |
252 detail::has_from_toml_method<T, C, M, V>, // but has from_toml(toml::value) | |
253 std::is_default_constructible<T> // and default constructible | |
254 >::value, T> | |
255 get(const basic_value<C, M, V>&); | |
256 | |
257 // toml::from<T>::from_toml(v) | |
258 template<typename T, typename C, | |
259 template<typename ...> class M, template<typename ...> class V> | |
260 detail::enable_if_t<detail::has_specialized_from<T>::value, T> | |
261 get(const basic_value<C, M, V>&); | |
262 | |
263 template<typename T, typename C, | |
264 template<typename ...> class M, template<typename ...> class V> | |
265 detail::enable_if_t<detail::has_specialized_from<T>::value, T> | |
266 get(basic_value<C, M, V>&); | |
267 | |
268 // T(const toml::value&) and T is not toml::basic_value, | |
269 // and it does not have `from<T>` nor `from_toml`. | |
270 template<typename T, typename C, | |
271 template<typename ...> class M, template<typename ...> class V> | |
272 detail::enable_if_t<detail::conjunction< | |
273 detail::negation<detail::is_basic_value<T>>, | |
274 std::is_constructible<T, const basic_value<C, M, V>&>, | |
275 detail::negation<detail::has_from_toml_method<T, C, M, V>>, | |
276 detail::negation<detail::has_specialized_from<T>> | |
277 >::value, T> | |
278 get(const basic_value<C, M, V>&); | |
279 | |
280 template<typename T, typename C, | |
281 template<typename ...> class M, template<typename ...> class V> | |
282 detail::enable_if_t<detail::conjunction< | |
283 detail::negation<detail::is_basic_value<T>>, | |
284 std::is_constructible<T, basic_value<C, M, V>&>, | |
285 detail::negation<detail::has_from_toml_method<T, C, M, V>>, | |
286 detail::negation<detail::has_specialized_from<T>> | |
287 >::value, T> | |
288 get(basic_value<C, M, V>&); | |
289 | |
290 // ============================================================================ | |
291 // array-like types; most likely STL container, like std::vector, etc. | |
292 | |
293 template<typename T, typename C, | |
294 template<typename ...> class M, template<typename ...> class V> | |
295 detail::enable_if_t<detail::conjunction< | |
296 detail::is_container<T>, // T is a container | |
297 detail::has_push_back_method<T>, // container.push_back(elem) works | |
298 detail::negation< // but not toml::array | |
299 detail::is_exact_toml_type<T, basic_value<C, M, V>>> | |
300 >::value, T> | |
301 get(const basic_value<C, M, V>& v) | |
302 { | |
303 using value_type = typename T::value_type; | |
304 const auto& ary = v.as_array(); | |
305 | |
306 T container; | |
307 try_reserve(container, ary.size()); | |
308 | |
309 for(const auto& elem : ary) | |
310 { | |
311 container.push_back(get<value_type>(elem)); | |
312 } | |
313 return container; | |
314 } | |
315 | |
316 // ============================================================================ | |
317 // std::forward_list does not have push_back, insert, or emplace. | |
318 // It has insert_after, emplace_after, push_front. | |
319 | |
320 template<typename T, typename C, | |
321 template<typename ...> class M, template<typename ...> class V> | |
322 detail::enable_if_t<detail::is_std_forward_list<T>::value, T> | |
323 get(const basic_value<C, M, V>& v) | |
324 { | |
325 using value_type = typename T::value_type; | |
326 T container; | |
327 for(const auto& elem : v.as_array()) | |
328 { | |
329 container.push_front(get<value_type>(elem)); | |
330 } | |
331 container.reverse(); | |
332 return container; | |
333 } | |
334 | |
335 // ============================================================================ | |
336 // array-like types, without push_back(). most likely [std|boost]::array. | |
337 | |
338 template<typename T, typename C, | |
339 template<typename ...> class M, template<typename ...> class V> | |
340 detail::enable_if_t<detail::conjunction< | |
341 detail::is_container<T>, // T is a container | |
342 detail::negation<detail::has_push_back_method<T>>, // w/o push_back | |
343 detail::negation<detail::has_specialized_from<T>>, // T does not have special conversion | |
344 detail::negation< // T is not toml::array | |
345 detail::is_exact_toml_type<T, basic_value<C, M, V>>> | |
346 >::value, T> | |
347 get(const basic_value<C, M, V>& v) | |
348 { | |
349 using value_type = typename T::value_type; | |
350 const auto& ar = v.as_array(); | |
351 | |
352 T container; | |
353 if(ar.size() != container.size()) | |
354 { | |
355 throw std::out_of_range(detail::format_underline(concat_to_string( | |
356 "toml::get: specified container size is ", container.size(), | |
357 " but there are ", ar.size(), " elements in toml array."), { | |
358 {v.location(), "here"} | |
359 })); | |
360 } | |
361 for(std::size_t i=0; i<ar.size(); ++i) | |
362 { | |
363 container[i] = ::toml::get<value_type>(ar[i]); | |
364 } | |
365 return container; | |
366 } | |
367 | |
368 // ============================================================================ | |
369 // std::pair. | |
370 | |
371 template<typename T, typename C, | |
372 template<typename ...> class M, template<typename ...> class V> | |
373 detail::enable_if_t<detail::is_std_pair<T>::value, T> | |
374 get(const basic_value<C, M, V>& v) | |
375 { | |
376 using first_type = typename T::first_type; | |
377 using second_type = typename T::second_type; | |
378 | |
379 const auto& ar = v.as_array(); | |
380 if(ar.size() != 2) | |
381 { | |
382 throw std::out_of_range(detail::format_underline(concat_to_string( | |
383 "toml::get: specified std::pair but there are ", ar.size(), | |
384 " elements in toml array."), {{v.location(), "here"}})); | |
385 } | |
386 return std::make_pair(::toml::get<first_type >(ar.at(0)), | |
387 ::toml::get<second_type>(ar.at(1))); | |
388 } | |
389 | |
390 // ============================================================================ | |
391 // std::tuple. | |
392 | |
393 namespace detail | |
394 { | |
395 template<typename T, typename Array, std::size_t ... I> | |
396 T get_tuple_impl(const Array& a, index_sequence<I...>) | |
397 { | |
398 return std::make_tuple( | |
399 ::toml::get<typename std::tuple_element<I, T>::type>(a.at(I))...); | |
400 } | |
401 } // detail | |
402 | |
403 template<typename T, typename C, | |
404 template<typename ...> class M, template<typename ...> class V> | |
405 detail::enable_if_t<detail::is_std_tuple<T>::value, T> | |
406 get(const basic_value<C, M, V>& v) | |
407 { | |
408 const auto& ar = v.as_array(); | |
409 if(ar.size() != std::tuple_size<T>::value) | |
410 { | |
411 throw std::out_of_range(detail::format_underline(concat_to_string( | |
412 "toml::get: specified std::tuple with ", | |
413 std::tuple_size<T>::value, " elements, but there are ", ar.size(), | |
414 " elements in toml array."), {{v.location(), "here"}})); | |
415 } | |
416 return detail::get_tuple_impl<T>(ar, | |
417 detail::make_index_sequence<std::tuple_size<T>::value>{}); | |
418 } | |
419 | |
420 // ============================================================================ | |
421 // map-like types; most likely STL map, like std::map or std::unordered_map. | |
422 | |
423 template<typename T, typename C, | |
424 template<typename ...> class M, template<typename ...> class V> | |
425 detail::enable_if_t<detail::conjunction< | |
426 detail::is_map<T>, // T is map | |
427 detail::negation< // but not toml::array | |
428 detail::is_exact_toml_type<T, basic_value<C, M, V>>> | |
429 >::value, T> | |
430 get(const basic_value<C, M, V>& v) | |
431 { | |
432 using key_type = typename T::key_type; | |
433 using mapped_type = typename T::mapped_type; | |
434 static_assert(std::is_convertible<std::string, key_type>::value, | |
435 "toml::get only supports map type of which key_type is " | |
436 "convertible from std::string."); | |
437 T map; | |
438 for(const auto& kv : v.as_table()) | |
439 { | |
440 map.emplace(key_type(kv.first), get<mapped_type>(kv.second)); | |
441 } | |
442 return map; | |
443 } | |
444 | |
445 // ============================================================================ | |
446 // user-defined, but compatible types. | |
447 | |
448 template<typename T, typename C, | |
449 template<typename ...> class M, template<typename ...> class V> | |
450 detail::enable_if_t<detail::conjunction< | |
451 detail::negation< // not a toml::* type | |
452 detail::is_exact_toml_type<T, basic_value<C, M, V>>>, | |
453 detail::has_from_toml_method<T, C, M, V>, // but has from_toml(toml::value) memfn | |
454 std::is_default_constructible<T> // and default constructible | |
455 >::value, T> | |
456 get(const basic_value<C, M, V>& v) | |
457 { | |
458 T ud; | |
459 ud.from_toml(v); | |
460 return ud; | |
461 } | |
462 template<typename T, typename C, | |
463 template<typename ...> class M, template<typename ...> class V> | |
464 detail::enable_if_t<detail::has_specialized_from<T>::value, T> | |
465 get(const basic_value<C, M, V>& v) | |
466 { | |
467 return ::toml::from<T>::from_toml(v); | |
468 } | |
469 template<typename T, typename C, | |
470 template<typename ...> class M, template<typename ...> class V> | |
471 detail::enable_if_t<detail::has_specialized_from<T>::value, T> | |
472 get(basic_value<C, M, V>& v) | |
473 { | |
474 return ::toml::from<T>::from_toml(v); | |
475 } | |
476 | |
477 template<typename T, typename C, | |
478 template<typename ...> class M, template<typename ...> class V> | |
479 detail::enable_if_t<detail::conjunction< | |
480 detail::negation<detail::is_basic_value<T>>, // T is not a toml::value | |
481 std::is_constructible<T, const basic_value<C, M, V>&>, // T is constructible from toml::value | |
482 detail::negation<detail::has_from_toml_method<T, C, M, V>>, // and T does not have T.from_toml(v); | |
483 detail::negation<detail::has_specialized_from<T>> // and T does not have toml::from<T>{}; | |
484 >::value, T> | |
485 get(const basic_value<C, M, V>& v) | |
486 { | |
487 return T(v); | |
488 } | |
489 | |
490 template<typename T, typename C, | |
491 template<typename ...> class M, template<typename ...> class V> | |
492 detail::enable_if_t<detail::conjunction< | |
493 detail::negation<detail::is_basic_value<T>>, // T is not a toml::value | |
494 std::is_constructible<T, basic_value<C, M, V>&>, // T is constructible from toml::value | |
495 detail::negation<detail::has_from_toml_method<T, C, M, V>>, // and T does not have T.from_toml(v); | |
496 detail::negation<detail::has_specialized_from<T>> // and T does not have toml::from<T>{}; | |
497 >::value, T> | |
498 get(basic_value<C, M, V>& v) | |
499 { | |
500 return T(v); | |
501 } | |
502 | |
503 // ============================================================================ | |
504 // find | |
505 | |
506 // ---------------------------------------------------------------------------- | |
507 // these overloads do not require to set T. and returns value itself. | |
508 template<typename C, | |
509 template<typename ...> class M, template<typename ...> class V> | |
510 basic_value<C, M, V> const& find(const basic_value<C, M, V>& v, const key& ky) | |
511 { | |
512 const auto& tab = v.as_table(); | |
513 if(tab.count(ky) == 0) | |
514 { | |
515 detail::throw_key_not_found_error(v, ky); | |
516 } | |
517 return tab.at(ky); | |
518 } | |
519 template<typename C, | |
520 template<typename ...> class M, template<typename ...> class V> | |
521 basic_value<C, M, V>& find(basic_value<C, M, V>& v, const key& ky) | |
522 { | |
523 auto& tab = v.as_table(); | |
524 if(tab.count(ky) == 0) | |
525 { | |
526 detail::throw_key_not_found_error(v, ky); | |
527 } | |
528 return tab.at(ky); | |
529 } | |
530 template<typename C, | |
531 template<typename ...> class M, template<typename ...> class V> | |
532 basic_value<C, M, V> find(basic_value<C, M, V>&& v, const key& ky) | |
533 { | |
534 typename basic_value<C, M, V>::table_type tab = std::move(v).as_table(); | |
535 if(tab.count(ky) == 0) | |
536 { | |
537 detail::throw_key_not_found_error(v, ky); | |
538 } | |
539 return basic_value<C, M, V>(std::move(tab.at(ky))); | |
540 } | |
541 | |
542 // ---------------------------------------------------------------------------- | |
543 // find(value, idx) | |
544 template<typename C, | |
545 template<typename ...> class M, template<typename ...> class V> | |
546 basic_value<C, M, V> const& | |
547 find(const basic_value<C, M, V>& v, const std::size_t idx) | |
548 { | |
549 const auto& ary = v.as_array(); | |
550 if(ary.size() <= idx) | |
551 { | |
552 throw std::out_of_range(detail::format_underline(concat_to_string( | |
553 "index ", idx, " is out of range"), {{v.location(), "in this array"}})); | |
554 } | |
555 return ary.at(idx); | |
556 } | |
557 template<typename C, | |
558 template<typename ...> class M, template<typename ...> class V> | |
559 basic_value<C, M, V>& find(basic_value<C, M, V>& v, const std::size_t idx) | |
560 { | |
561 auto& ary = v.as_array(); | |
562 if(ary.size() <= idx) | |
563 { | |
564 throw std::out_of_range(detail::format_underline(concat_to_string( | |
565 "index ", idx, " is out of range"), {{v.location(), "in this array"}})); | |
566 } | |
567 return ary.at(idx); | |
568 } | |
569 template<typename C, | |
570 template<typename ...> class M, template<typename ...> class V> | |
571 basic_value<C, M, V> find(basic_value<C, M, V>&& v, const std::size_t idx) | |
572 { | |
573 auto& ary = v.as_array(); | |
574 if(ary.size() <= idx) | |
575 { | |
576 throw std::out_of_range(detail::format_underline(concat_to_string( | |
577 "index ", idx, " is out of range"), {{v.location(), "in this array"}})); | |
578 } | |
579 return basic_value<C, M, V>(std::move(ary.at(idx))); | |
580 } | |
581 | |
582 // ---------------------------------------------------------------------------- | |
583 // find<T>(value, key); | |
584 | |
585 template<typename T, typename C, | |
586 template<typename ...> class M, template<typename ...> class V> | |
587 decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>())) | |
588 find(const basic_value<C, M, V>& v, const key& ky) | |
589 { | |
590 const auto& tab = v.as_table(); | |
591 if(tab.count(ky) == 0) | |
592 { | |
593 detail::throw_key_not_found_error(v, ky); | |
594 } | |
595 return ::toml::get<T>(tab.at(ky)); | |
596 } | |
597 | |
598 template<typename T, typename C, | |
599 template<typename ...> class M, template<typename ...> class V> | |
600 decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>())) | |
601 find(basic_value<C, M, V>& v, const key& ky) | |
602 { | |
603 auto& tab = v.as_table(); | |
604 if(tab.count(ky) == 0) | |
605 { | |
606 detail::throw_key_not_found_error(v, ky); | |
607 } | |
608 return ::toml::get<T>(tab.at(ky)); | |
609 } | |
610 | |
611 template<typename T, typename C, | |
612 template<typename ...> class M, template<typename ...> class V> | |
613 decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>())) | |
614 find(basic_value<C, M, V>&& v, const key& ky) | |
615 { | |
616 typename basic_value<C, M, V>::table_type tab = std::move(v).as_table(); | |
617 if(tab.count(ky) == 0) | |
618 { | |
619 detail::throw_key_not_found_error(v, ky); | |
620 } | |
621 return ::toml::get<T>(std::move(tab.at(ky))); | |
622 } | |
623 | |
624 // ---------------------------------------------------------------------------- | |
625 // find<T>(value, idx) | |
626 template<typename T, typename C, | |
627 template<typename ...> class M, template<typename ...> class V> | |
628 decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>())) | |
629 find(const basic_value<C, M, V>& v, const std::size_t idx) | |
630 { | |
631 const auto& ary = v.as_array(); | |
632 if(ary.size() <= idx) | |
633 { | |
634 throw std::out_of_range(detail::format_underline(concat_to_string( | |
635 "index ", idx, " is out of range"), {{v.location(), "in this array"}})); | |
636 } | |
637 return ::toml::get<T>(ary.at(idx)); | |
638 } | |
639 template<typename T, typename C, | |
640 template<typename ...> class M, template<typename ...> class V> | |
641 decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>())) | |
642 find(basic_value<C, M, V>& v, const std::size_t idx) | |
643 { | |
644 auto& ary = v.as_array(); | |
645 if(ary.size() <= idx) | |
646 { | |
647 throw std::out_of_range(detail::format_underline(concat_to_string( | |
648 "index ", idx, " is out of range"), {{v.location(), "in this array"}})); | |
649 } | |
650 return ::toml::get<T>(ary.at(idx)); | |
651 } | |
652 template<typename T, typename C, | |
653 template<typename ...> class M, template<typename ...> class V> | |
654 decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>())) | |
655 find(basic_value<C, M, V>&& v, const std::size_t idx) | |
656 { | |
657 typename basic_value<C, M, V>::array_type ary = std::move(v).as_array(); | |
658 if(ary.size() <= idx) | |
659 { | |
660 throw std::out_of_range(detail::format_underline(concat_to_string( | |
661 "index ", idx, " is out of range"), {{v.location(), "in this array"}})); | |
662 } | |
663 return ::toml::get<T>(std::move(ary.at(idx))); | |
664 } | |
665 | |
666 // -------------------------------------------------------------------------- | |
667 // toml::find(toml::value, toml::key, Ts&& ... keys) | |
668 | |
669 namespace detail | |
670 { | |
671 // It suppresses warnings by -Wsign-conversion. Let's say we have the following | |
672 // code. | |
673 // ```cpp | |
674 // const auto x = toml::find<std::string>(data, "array", 0); | |
675 // ``` | |
676 // Here, the type of literal number `0` is `int`. `int` is a signed integer. | |
677 // `toml::find` takes `std::size_t` as an index. So it causes implicit sign | |
678 // conversion and `-Wsign-conversion` warns about it. Using `0u` instead of `0` | |
679 // suppresses the warning, but it makes user code messy. | |
680 // To suppress this warning, we need to be aware of type conversion caused | |
681 // by `toml::find(v, key1, key2, ... keys)`. But the thing is that the types of | |
682 // keys can be any combination of {string-like, size_t-like}. Of course we can't | |
683 // write down all the combinations. Thus we need to use some function that | |
684 // recognize the type of argument and cast it into `std::string` or | |
685 // `std::size_t` depending on the context. | |
686 // `key_cast` does the job. It has 2 overloads. One is invoked when the | |
687 // argument type is an integer and cast the argument into `std::size_t`. The | |
688 // other is invoked when the argument type is not an integer, possibly one of | |
689 // std::string, const char[N] or const char*, and construct std::string from | |
690 // the argument. | |
691 // `toml::find(v, k1, k2, ... ks)` uses `key_cast` before passing `ks` to | |
692 // `toml::find(v, k)` to suppress -Wsign-conversion. | |
693 | |
694 template<typename T> | |
695 enable_if_t<conjunction<std::is_integral<remove_cvref_t<T>>, | |
696 negation<std::is_same<remove_cvref_t<T>, bool>>>::value, std::size_t> | |
697 key_cast(T&& v) noexcept | |
698 { | |
699 return std::size_t(v); | |
700 } | |
701 template<typename T> | |
702 enable_if_t<negation<conjunction<std::is_integral<remove_cvref_t<T>>, | |
703 negation<std::is_same<remove_cvref_t<T>, bool>>>>::value, std::string> | |
704 key_cast(T&& v) noexcept | |
705 { | |
706 return std::string(std::forward<T>(v)); | |
707 } | |
708 } // detail | |
709 | |
710 template<typename C, | |
711 template<typename ...> class M, template<typename ...> class V, | |
712 typename Key1, typename Key2, typename ... Keys> | |
713 const basic_value<C, M, V>& | |
714 find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys) | |
715 { | |
716 return ::toml::find(::toml::find(v, detail::key_cast(k1)), | |
717 detail::key_cast(k2), std::forward<Keys>(keys)...); | |
718 } | |
719 template<typename C, | |
720 template<typename ...> class M, template<typename ...> class V, | |
721 typename Key1, typename Key2, typename ... Keys> | |
722 basic_value<C, M, V>& | |
723 find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys) | |
724 { | |
725 return ::toml::find(::toml::find(v, detail::key_cast(k1)), | |
726 detail::key_cast(k2), std::forward<Keys>(keys)...); | |
727 } | |
728 template<typename C, | |
729 template<typename ...> class M, template<typename ...> class V, | |
730 typename Key1, typename Key2, typename ... Keys> | |
731 basic_value<C, M, V> | |
732 find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys) | |
733 { | |
734 return ::toml::find(::toml::find(std::move(v), std::forward<Key1>(k1)), | |
735 detail::key_cast(k2), std::forward<Keys>(keys)...); | |
736 } | |
737 | |
738 template<typename T, typename C, | |
739 template<typename ...> class M, template<typename ...> class V, | |
740 typename Key1, typename Key2, typename ... Keys> | |
741 decltype(::toml::get<T>(std::declval<const basic_value<C, M, V>&>())) | |
742 find(const basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys) | |
743 { | |
744 return ::toml::find<T>(::toml::find(v, detail::key_cast(k1)), | |
745 detail::key_cast(k2), std::forward<Keys>(keys)...); | |
746 } | |
747 template<typename T, typename C, | |
748 template<typename ...> class M, template<typename ...> class V, | |
749 typename Key1, typename Key2, typename ... Keys> | |
750 decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>())) | |
751 find(basic_value<C, M, V>& v, Key1&& k1, Key2&& k2, Keys&& ... keys) | |
752 { | |
753 return ::toml::find<T>(::toml::find(v, detail::key_cast(k1)), | |
754 detail::key_cast(k2), std::forward<Keys>(keys)...); | |
755 } | |
756 template<typename T, typename C, | |
757 template<typename ...> class M, template<typename ...> class V, | |
758 typename Key1, typename Key2, typename ... Keys> | |
759 decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>())) | |
760 find(basic_value<C, M, V>&& v, Key1&& k1, Key2&& k2, Keys&& ... keys) | |
761 { | |
762 return ::toml::find<T>(::toml::find(std::move(v), detail::key_cast(k1)), | |
763 detail::key_cast(k2), std::forward<Keys>(keys)...); | |
764 } | |
765 | |
766 // ============================================================================ | |
767 // get_or(value, fallback) | |
768 | |
769 template<typename C, | |
770 template<typename ...> class M, template<typename ...> class V> | |
771 basic_value<C, M, V> const& | |
772 get_or(const basic_value<C, M, V>& v, const basic_value<C, M, V>&) | |
773 { | |
774 return v; | |
775 } | |
776 template<typename C, | |
777 template<typename ...> class M, template<typename ...> class V> | |
778 basic_value<C, M, V>& | |
779 get_or(basic_value<C, M, V>& v, basic_value<C, M, V>&) | |
780 { | |
781 return v; | |
782 } | |
783 template<typename C, | |
784 template<typename ...> class M, template<typename ...> class V> | |
785 basic_value<C, M, V> | |
786 get_or(basic_value<C, M, V>&& v, basic_value<C, M, V>&&) | |
787 { | |
788 return v; | |
789 } | |
790 | |
791 // ---------------------------------------------------------------------------- | |
792 // specialization for the exact toml types (return type becomes lvalue ref) | |
793 | |
794 template<typename T, typename C, | |
795 template<typename ...> class M, template<typename ...> class V> | |
796 detail::enable_if_t< | |
797 detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const& | |
798 get_or(const basic_value<C, M, V>& v, const T& opt) | |
799 { | |
800 try | |
801 { | |
802 return get<detail::remove_cvref_t<T>>(v); | |
803 } | |
804 catch(...) | |
805 { | |
806 return opt; | |
807 } | |
808 } | |
809 template<typename T, typename C, | |
810 template<typename ...> class M, template<typename ...> class V> | |
811 detail::enable_if_t< | |
812 detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>& | |
813 get_or(basic_value<C, M, V>& v, T& opt) | |
814 { | |
815 try | |
816 { | |
817 return get<detail::remove_cvref_t<T>>(v); | |
818 } | |
819 catch(...) | |
820 { | |
821 return opt; | |
822 } | |
823 } | |
824 template<typename T, typename C, | |
825 template<typename ...> class M, template<typename ...> class V> | |
826 detail::enable_if_t<detail::is_exact_toml_type<detail::remove_cvref_t<T>, | |
827 basic_value<C, M, V>>::value, detail::remove_cvref_t<T>> | |
828 get_or(basic_value<C, M, V>&& v, T&& opt) | |
829 { | |
830 try | |
831 { | |
832 return get<detail::remove_cvref_t<T>>(std::move(v)); | |
833 } | |
834 catch(...) | |
835 { | |
836 return detail::remove_cvref_t<T>(std::forward<T>(opt)); | |
837 } | |
838 } | |
839 | |
840 // ---------------------------------------------------------------------------- | |
841 // specialization for std::string (return type becomes lvalue ref) | |
842 | |
843 template<typename T, typename C, | |
844 template<typename ...> class M, template<typename ...> class V> | |
845 detail::enable_if_t<std::is_same<detail::remove_cvref_t<T>, std::string>::value, | |
846 std::string> const& | |
847 get_or(const basic_value<C, M, V>& v, const T& opt) | |
848 { | |
849 try | |
850 { | |
851 return v.as_string().str; | |
852 } | |
853 catch(...) | |
854 { | |
855 return opt; | |
856 } | |
857 } | |
858 template<typename T, typename C, | |
859 template<typename ...> class M, template<typename ...> class V> | |
860 detail::enable_if_t<std::is_same<T, std::string>::value, std::string>& | |
861 get_or(basic_value<C, M, V>& v, T& opt) | |
862 { | |
863 try | |
864 { | |
865 return v.as_string().str; | |
866 } | |
867 catch(...) | |
868 { | |
869 return opt; | |
870 } | |
871 } | |
872 template<typename T, typename C, | |
873 template<typename ...> class M, template<typename ...> class V> | |
874 detail::enable_if_t< | |
875 std::is_same<detail::remove_cvref_t<T>, std::string>::value, std::string> | |
876 get_or(basic_value<C, M, V>&& v, T&& opt) | |
877 { | |
878 try | |
879 { | |
880 return std::move(v.as_string().str); | |
881 } | |
882 catch(...) | |
883 { | |
884 return std::string(std::forward<T>(opt)); | |
885 } | |
886 } | |
887 | |
888 // ---------------------------------------------------------------------------- | |
889 // specialization for string literal | |
890 | |
891 template<typename T, typename C, | |
892 template<typename ...> class M, template<typename ...> class V> | |
893 detail::enable_if_t<detail::is_string_literal< | |
894 typename std::remove_reference<T>::type>::value, std::string> | |
895 get_or(const basic_value<C, M, V>& v, T&& opt) | |
896 { | |
897 try | |
898 { | |
899 return std::move(v.as_string().str); | |
900 } | |
901 catch(...) | |
902 { | |
903 return std::string(std::forward<T>(opt)); | |
904 } | |
905 } | |
906 | |
907 // ---------------------------------------------------------------------------- | |
908 // others (require type conversion and return type cannot be lvalue reference) | |
909 | |
910 template<typename T, typename C, | |
911 template<typename ...> class M, template<typename ...> class V> | |
912 detail::enable_if_t<detail::conjunction< | |
913 detail::negation<detail::is_exact_toml_type<detail::remove_cvref_t<T>, | |
914 basic_value<C, M, V>>>, | |
915 detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>, | |
916 detail::negation<detail::is_string_literal< | |
917 typename std::remove_reference<T>::type>> | |
918 >::value, detail::remove_cvref_t<T>> | |
919 get_or(const basic_value<C, M, V>& v, T&& opt) | |
920 { | |
921 try | |
922 { | |
923 return get<detail::remove_cvref_t<T>>(v); | |
924 } | |
925 catch(...) | |
926 { | |
927 return detail::remove_cvref_t<T>(std::forward<T>(opt)); | |
928 } | |
929 } | |
930 | |
931 // =========================================================================== | |
932 // find_or(value, key, fallback) | |
933 | |
934 template<typename C, | |
935 template<typename ...> class M, template<typename ...> class V> | |
936 basic_value<C, M, V> const& | |
937 find_or(const basic_value<C, M, V>& v, const key& ky, | |
938 const basic_value<C, M, V>& opt) | |
939 { | |
940 if(!v.is_table()) {return opt;} | |
941 const auto& tab = v.as_table(); | |
942 if(tab.count(ky) == 0) {return opt;} | |
943 return tab.at(ky); | |
944 } | |
945 | |
946 template<typename C, | |
947 template<typename ...> class M, template<typename ...> class V> | |
948 basic_value<C, M, V>& | |
949 find_or(basic_value<C, M, V>& v, const toml::key& ky, basic_value<C, M, V>& opt) | |
950 { | |
951 if(!v.is_table()) {return opt;} | |
952 auto& tab = v.as_table(); | |
953 if(tab.count(ky) == 0) {return opt;} | |
954 return tab.at(ky); | |
955 } | |
956 | |
957 template<typename C, | |
958 template<typename ...> class M, template<typename ...> class V> | |
959 basic_value<C, M, V> | |
960 find_or(basic_value<C, M, V>&& v, const toml::key& ky, basic_value<C, M, V>&& opt) | |
961 { | |
962 if(!v.is_table()) {return opt;} | |
963 auto tab = std::move(v).as_table(); | |
964 if(tab.count(ky) == 0) {return opt;} | |
965 return basic_value<C, M, V>(std::move(tab.at(ky))); | |
966 } | |
967 | |
968 // --------------------------------------------------------------------------- | |
969 // exact types (return type can be a reference) | |
970 template<typename T, typename C, | |
971 template<typename ...> class M, template<typename ...> class V> | |
972 detail::enable_if_t< | |
973 detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const& | |
974 find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt) | |
975 { | |
976 if(!v.is_table()) {return opt;} | |
977 const auto& tab = v.as_table(); | |
978 if(tab.count(ky) == 0) {return opt;} | |
979 return get_or(tab.at(ky), opt); | |
980 } | |
981 | |
982 template<typename T, typename C, | |
983 template<typename ...> class M, template<typename ...> class V> | |
984 detail::enable_if_t< | |
985 detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>& | |
986 find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt) | |
987 { | |
988 if(!v.is_table()) {return opt;} | |
989 auto& tab = v.as_table(); | |
990 if(tab.count(ky) == 0) {return opt;} | |
991 return get_or(tab.at(ky), opt); | |
992 } | |
993 | |
994 template<typename T, typename C, | |
995 template<typename ...> class M, template<typename ...> class V> | |
996 detail::enable_if_t< | |
997 detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, | |
998 detail::remove_cvref_t<T>> | |
999 find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt) | |
1000 { | |
1001 if(!v.is_table()) {return std::forward<T>(opt);} | |
1002 auto tab = std::move(v).as_table(); | |
1003 if(tab.count(ky) == 0) {return std::forward<T>(opt);} | |
1004 return get_or(std::move(tab.at(ky)), std::forward<T>(opt)); | |
1005 } | |
1006 | |
1007 // --------------------------------------------------------------------------- | |
1008 // std::string (return type can be a reference) | |
1009 | |
1010 template<typename T, typename C, | |
1011 template<typename ...> class M, template<typename ...> class V> | |
1012 detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const& | |
1013 find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt) | |
1014 { | |
1015 if(!v.is_table()) {return opt;} | |
1016 const auto& tab = v.as_table(); | |
1017 if(tab.count(ky) == 0) {return opt;} | |
1018 return get_or(tab.at(ky), opt); | |
1019 } | |
1020 template<typename T, typename C, | |
1021 template<typename ...> class M, template<typename ...> class V> | |
1022 detail::enable_if_t<std::is_same<T, std::string>::value, std::string>& | |
1023 find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt) | |
1024 { | |
1025 if(!v.is_table()) {return opt;} | |
1026 auto& tab = v.as_table(); | |
1027 if(tab.count(ky) == 0) {return opt;} | |
1028 return get_or(tab.at(ky), opt); | |
1029 } | |
1030 template<typename T, typename C, | |
1031 template<typename ...> class M, template<typename ...> class V> | |
1032 detail::enable_if_t<std::is_same<T, std::string>::value, std::string> | |
1033 find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt) | |
1034 { | |
1035 if(!v.is_table()) {return std::forward<T>(opt);} | |
1036 auto tab = std::move(v).as_table(); | |
1037 if(tab.count(ky) == 0) {return std::forward<T>(opt);} | |
1038 return get_or(std::move(tab.at(ky)), std::forward<T>(opt)); | |
1039 } | |
1040 | |
1041 // --------------------------------------------------------------------------- | |
1042 // string literal (deduced as std::string) | |
1043 template<typename T, typename C, | |
1044 template<typename ...> class M, template<typename ...> class V> | |
1045 detail::enable_if_t< | |
1046 detail::is_string_literal<typename std::remove_reference<T>::type>::value, | |
1047 std::string> | |
1048 find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt) | |
1049 { | |
1050 if(!v.is_table()) {return std::string(opt);} | |
1051 const auto& tab = v.as_table(); | |
1052 if(tab.count(ky) == 0) {return std::string(opt);} | |
1053 return get_or(tab.at(ky), std::forward<T>(opt)); | |
1054 } | |
1055 | |
1056 // --------------------------------------------------------------------------- | |
1057 // others (require type conversion and return type cannot be lvalue reference) | |
1058 template<typename T, typename C, | |
1059 template<typename ...> class M, template<typename ...> class V> | |
1060 detail::enable_if_t<detail::conjunction< | |
1061 // T is not an exact toml type | |
1062 detail::negation<detail::is_exact_toml_type< | |
1063 detail::remove_cvref_t<T>, basic_value<C, M, V>>>, | |
1064 // T is not std::string | |
1065 detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>, | |
1066 // T is not a string literal | |
1067 detail::negation<detail::is_string_literal< | |
1068 typename std::remove_reference<T>::type>> | |
1069 >::value, detail::remove_cvref_t<T>> | |
1070 find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt) | |
1071 { | |
1072 if(!v.is_table()) {return std::forward<T>(opt);} | |
1073 const auto& tab = v.as_table(); | |
1074 if(tab.count(ky) == 0) {return std::forward<T>(opt);} | |
1075 return get_or(tab.at(ky), std::forward<T>(opt)); | |
1076 } | |
1077 | |
1078 // --------------------------------------------------------------------------- | |
1079 // recursive find-or with type deduction (find_or(value, keys, opt)) | |
1080 | |
1081 template<typename Value, typename ... Ks, | |
1082 typename detail::enable_if_t<(sizeof...(Ks) > 1), std::nullptr_t> = nullptr> | |
1083 // here we need to add SFINAE in the template parameter to avoid | |
1084 // infinite recursion in type deduction on gcc | |
1085 auto find_or(Value&& v, const toml::key& ky, Ks&& ... keys) | |
1086 -> decltype(find_or(std::forward<Value>(v), ky, detail::last_one(std::forward<Ks>(keys)...))) | |
1087 { | |
1088 if(!v.is_table()) | |
1089 { | |
1090 return detail::last_one(std::forward<Ks>(keys)...); | |
1091 } | |
1092 auto&& tab = std::forward<Value>(v).as_table(); | |
1093 if(tab.count(ky) == 0) | |
1094 { | |
1095 return detail::last_one(std::forward<Ks>(keys)...); | |
1096 } | |
1097 return find_or(std::forward<decltype(tab)>(tab).at(ky), std::forward<Ks>(keys)...); | |
1098 } | |
1099 | |
1100 // --------------------------------------------------------------------------- | |
1101 // recursive find_or with explicit type specialization, find_or<int>(value, keys...) | |
1102 | |
1103 template<typename T, typename Value, typename ... Ks, | |
1104 typename detail::enable_if_t<(sizeof...(Ks) > 1), std::nullptr_t> = nullptr> | |
1105 // here we need to add SFINAE in the template parameter to avoid | |
1106 // infinite recursion in type deduction on gcc | |
1107 auto find_or(Value&& v, const toml::key& ky, Ks&& ... keys) | |
1108 -> decltype(find_or<T>(std::forward<Value>(v), ky, detail::last_one(std::forward<Ks>(keys)...))) | |
1109 { | |
1110 if(!v.is_table()) | |
1111 { | |
1112 return detail::last_one(std::forward<Ks>(keys)...); | |
1113 } | |
1114 auto&& tab = std::forward<Value>(v).as_table(); | |
1115 if(tab.count(ky) == 0) | |
1116 { | |
1117 return detail::last_one(std::forward<Ks>(keys)...); | |
1118 } | |
1119 return find_or(std::forward<decltype(tab)>(tab).at(ky), std::forward<Ks>(keys)...); | |
1120 } | |
1121 | |
1122 // ============================================================================ | |
1123 // expect | |
1124 | |
1125 template<typename T, typename C, | |
1126 template<typename ...> class M, template<typename ...> class V> | |
1127 result<T, std::string> expect(const basic_value<C, M, V>& v) noexcept | |
1128 { | |
1129 try | |
1130 { | |
1131 return ok(get<T>(v)); | |
1132 } | |
1133 catch(const std::exception& e) | |
1134 { | |
1135 return err(e.what()); | |
1136 } | |
1137 } | |
1138 template<typename T, typename C, | |
1139 template<typename ...> class M, template<typename ...> class V> | |
1140 result<T, std::string> | |
1141 expect(const basic_value<C, M, V>& v, const toml::key& k) noexcept | |
1142 { | |
1143 try | |
1144 { | |
1145 return ok(find<T>(v, k)); | |
1146 } | |
1147 catch(const std::exception& e) | |
1148 { | |
1149 return err(e.what()); | |
1150 } | |
1151 } | |
1152 | |
1153 } // toml | |
1154 #endif// TOML11_GET |