1 //     Copyright Toru Niina 2019.
2 // Distributed under the MIT License.
3 #ifndef TOML11_LITERAL_HPP
4 #define TOML11_LITERAL_HPP
5 #include "parser.hpp"
6 
7 namespace toml
8 {
9 inline namespace literals
10 {
11 inline namespace toml_literals
12 {
13 
14 // implementation
15 inline ::toml::basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>
literal_internal_impl(::toml::detail::location loc)16 literal_internal_impl(::toml::detail::location loc)
17 {
18     using value_type = ::toml::basic_value<
19         TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>;
20     // if there are some comments or empty lines, skip them.
21     using skip_line = ::toml::detail::repeat<toml::detail::sequence<
22             ::toml::detail::maybe<::toml::detail::lex_ws>,
23             ::toml::detail::maybe<::toml::detail::lex_comment>,
24             ::toml::detail::lex_newline
25         >, ::toml::detail::at_least<1>>;
26     skip_line::invoke(loc);
27 
28     // if there are some whitespaces before a value, skip them.
29     using skip_ws = ::toml::detail::repeat<
30         ::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
31     skip_ws::invoke(loc);
32 
33     // to distinguish arrays and tables, first check it is a table or not.
34     //
35     // "[1,2,3]"_toml;   // this is an array
36     // "[table]"_toml;   // a table that has an empty table named "table" inside.
37     // "[[1,2,3]]"_toml; // this is an array of arrays
38     // "[[table]]"_toml; // this is a table that has an array of tables inside.
39     //
40     // "[[1]]"_toml;     // this can be both... (currently it becomes a table)
41     // "1 = [{}]"_toml;  // this is a table that has an array of table named 1.
42     // "[[1,]]"_toml;    // this is an array of arrays.
43     // "[[1],]"_toml;    // this also.
44 
45     const auto the_front = loc.iter();
46 
47     const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc);
48     loc.reset(the_front);
49 
50     const bool is_aots_key  = ::toml::detail::lex_array_table::invoke(loc);
51     loc.reset(the_front);
52 
53     // If it is neither a table-key or a array-of-table-key, it may be a value.
54     if(!is_table_key && !is_aots_key)
55     {
56         if(auto data = ::toml::detail::parse_value<value_type>(loc))
57         {
58             return data.unwrap();
59         }
60     }
61 
62     // Note that still it can be a table, because the literal might be something
63     // like the following.
64     // ```cpp
65     // R"( // c++11 raw string literals
66     //   key = "value"
67     //   int = 42
68     // )"_toml;
69     // ```
70     // It is a valid toml file.
71     // It should be parsed as if we parse a file with this content.
72 
73     if(auto data = ::toml::detail::parse_toml_file<value_type>(loc))
74     {
75         return data.unwrap();
76     }
77     else // none of them.
78     {
79         throw ::toml::syntax_error(data.unwrap_err(), source_location(loc));
80     }
81 
82 }
83 
84 inline ::toml::basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>
operator ""_toml(const char * str,std::size_t len)85 operator"" _toml(const char* str, std::size_t len)
86 {
87     ::toml::detail::location loc(
88             std::string("TOML literal encoded in a C++ code"),
89             std::vector<char>(str, str + len));
90     return literal_internal_impl(std::move(loc));
91 }
92 
93 // value of __cplusplus in C++2a/20 mode is not fixed yet along compilers.
94 // So here we use the feature test macro for `char8_t` itself.
95 #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
96 // value of u8"" literal has been changed from char to char8_t and char8_t is
97 // NOT compatible to char
98 inline ::toml::basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>
operator ""_toml(const char8_t * str,std::size_t len)99 operator"" _toml(const char8_t* str, std::size_t len)
100 {
101     ::toml::detail::location loc(
102             std::string("TOML literal encoded in a C++ code"),
103             std::vector<char>(reinterpret_cast<const char*>(str),
104                               reinterpret_cast<const char*>(str) + len));
105     return literal_internal_impl(std::move(loc));
106 }
107 #endif
108 
109 } // toml_literals
110 } // literals
111 } // toml
112 #endif//TOML11_LITERAL_HPP
113