added array::get

also:
- moved node_of to impl namespace
- added a lot more documentation
- fixed some bugs in the documentation generator
- fixed the license ID breaking github's license recognition
This commit is contained in:
Mark Gillard 2020-02-16 15:11:57 +02:00
parent c7483cb92c
commit 1f8f3c7baa
15 changed files with 767 additions and 269 deletions

View File

@ -14,5 +14,3 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SPDX-License-Identifier: MIT

View File

@ -30,6 +30,27 @@ std::string_view library_version = config["library"]["version"].as_string()->get
std::string_view library_author = config["library"]["authors"][0].as_string()->get();
int64_t depends_on_cpp_version = config["dependencies"]["cpp"].as_integer()->get();
// modify the data
config.insert_or_assign("alternatives", toml::array{
"cpptoml",
"toml11",
"Boost.TOML"
});
// iterate & visit over the data
for (auto [k, v] : config)
{
v.visit([](auto& node) noexcept
{
std::cout << node << std:endl;
if constexpr (toml::is_string<decltype(node)>)
do_something_with_string_values(node)
});
}
// re-serialize as TOML
std::cout << config << std::endl;
// re-serialize as JSON
std::cout << toml::json_formatter{ config } << std::endl;

View File

@ -82,7 +82,7 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_INCLUDE_FILES = NO
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
@ -112,7 +112,7 @@ WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = YES
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE = ./doc/doxygen_warnings.log
#---------------------------------------------------------------------------
@ -202,7 +202,7 @@ IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
GENERATE_HTML = NO
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
@ -302,9 +302,9 @@ MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
GENERATE_XML = YES
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
XML_PROGRAMLISTING = NO
XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
@ -336,7 +336,8 @@ PREDEFINED = TOML_DOXYGEN=1 \
__cplusplus=201703L \
TOML_ALWAYS_INLINE=inline \
TOML_MAY_THROW= \
TOML_NODISCARD_CTOR=
TOML_NODISCARD_CTOR= \
__cpp_lib_char8_t=201811L
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = NO
#---------------------------------------------------------------------------

View File

@ -1,14 +1,8 @@
@INCLUDE = ./Doxyfile
GENERATE_HTML = NO
GENERATE_XML = YES
XML_PROGRAMLISTING = NO
HTML_EXTRA_STYLESHEET = https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400i,600,600i%7CSource+Code+Pro:400,400i,600 \
../css/m-dark+documentation.compiled.css \
tomlplusplus.css
WARN_AS_ERROR = NO
TAB_SIZE = 4
HTML_EXTRA_FILES = tomlplusplus.js
SHOW_INCLUDE_FILES = NO
##! M_THEME_COLOR = #22272e
##! M_LINKS_NAVBAR1 = \
##! namespaces
@ -22,4 +16,3 @@ SHOW_INCLUDE_FILES = NO
##! <a target="_blank" href="https://github.com/marzer/tomlplusplus/issues">Report an issue</a> \
##! <br><br>Documentation generated using <a href="https://mcss.mosra.cz/">m.css</a>
##! M_HTML_HEADER = <script src="tomlplusplus.js"></script>
##! M_MAIN_PROJECT_URL = https://github.com/marzer/tomlplusplus/

View File

@ -62,21 +62,6 @@ dl.m-doc dd
color: inherit;
}
body > header > nav
{
background-color: #1e1e1e;
}
html
{
background-color: #2d2d30;
}
pre, code, .m-label, .tpp-enable-if > a
{
font-family: 'Consolas', monospace;
}
pre, .m-doc-search-content
{
background-color: #1e1e1e;
@ -186,28 +171,71 @@ nav .m-thin {
margin-left: 0.5em;
}
.m-code .c1 {
color: rgb(87,166,74);
}
.m-code .mi, .m-code .mf {
color: rgb(181,206,168);
}
.m-code .k {
color: rgb(86,156,214);
}
.m-code .n {
color: rgb(220,220,220);
}
.m-code .p {
color: rgb(120,120,120);
}
.m-doc-details div table.m-table.m-fullwidth.m-flat thead tr th,
.m-doc-details div table.m-table.m-fullwidth.m-flat tfoot tr th
{
color: #a5c9ea;
}
/* comments */
.m-code .c1
{
color: rgb(87,166,74);
}
/* int and float literals */
.m-code .mi,
.m-code .mf
{
color: rgb(181,206,168);
}
/* keywords */
.m-code .k
{
color: rgb(86,156,214);
}
/* identifier names */
.m-code .n
{
color: rgb(220,220,220);
}
/* punctuators (brackets etc) */
.m-code .p
{
color: rgb(120,120,120);
}
/* preprocessor directives */
.m-code .cp
{
color: rgb(120,120,120);
}
/* string literals, "includes" */
.m-code .s,
.m-code .s + .n,
.m-code .cpf
{
color: rgb(214,157,133);
}
.m-code .kt,
.m-code .k
{
font-weight: normal;
}
/* user types and typedefs */
.m-code .ut
{
color: rgb(78,201,176);
}
/* namespace::scopes:: */
.m-code .ns
{
color: rgb(140,140,140);
}

View File

@ -188,8 +188,8 @@ namespace toml
///
/// \detail \cpp
///
/// auto table = toml::parse("arr = [1, 2, 3, 4, 'five']"sv);
/// auto& arr = *table.get_as<toml::array>("arr");
/// auto tbl = toml::parse("arr = [1, 2, 3, 4, 'five']"sv);
/// auto& arr = *tbl.get_as<toml::array>("arr");
/// std::cout << arr << std::endl;
///
/// for (size_t i = 0; i < arr.size(); i++)
@ -265,12 +265,7 @@ namespace toml
/// \brief Constructs an array with one or more initial values.
///
/// \detail \cpp
/// auto arr = toml::array{
/// 1,
/// 2.0,
/// "three"sv,
/// toml::array{ 4, 5 }
/// };
/// auto arr = toml::array{ 1, 2.0, "three"sv, toml::array{ 4, 5 } };
/// std::cout << arr << std::endl;
///
/// // output:
@ -304,7 +299,7 @@ namespace toml
return *this;
}
/// \brief Always returns `node_type::array` for array nodes.
/// \brief Always returns node_type::array for array nodes.
[[nodiscard]] node_type type() const noexcept override { return node_type::array; }
/// \brief Always returns `false` for array nodes.
[[nodiscard]] bool is_table() const noexcept override { return false; }
@ -318,11 +313,7 @@ namespace toml
/// \brief Checks if the array contains nodes of only one type.
///
/// \detail \cpp
/// auto arr = toml::array{
/// 1,
/// 2,
/// 3
/// };
/// auto arr = toml::array{ 1, 2, 3 };
/// std::cout << "homogenous: "sv << arr.is_homogeneous() << std::endl;
/// std::cout << "all doubles: "sv << arr.is_homogeneous<double>() << std::endl;
/// std::cout << "all arrays: "sv << arr.is_homogeneous<toml::array>() << std::endl;
@ -411,10 +402,7 @@ namespace toml
/// \brief Inserts a new node at a specific position in the array.
///
/// \detail \cpp
/// auto arr = toml::array{
/// 1,
/// 3
/// };
/// auto arr = toml::array{ 1, 3 };
/// arr.insert(arr.cbegin() + 1, "two");
/// arr.insert(arr.cend(), toml::array{ 4, 5 });
/// std::cout << arr << std::endl;
@ -539,10 +527,7 @@ namespace toml
/// \brief Emplaces a new value at a specific position in the array.
///
/// \detail \cpp
/// auto arr = toml::array{
/// 1,
/// 2
/// };
/// auto arr = toml::array{ 1, 2 };
///
/// //add a string using std::string's substring constructor
/// arr.emplace<std::string>(arr.cbegin() + 1, "this is not a drill"sv, 14, 5);
@ -555,12 +540,12 @@ namespace toml
/// \tparam U One of the TOML node or value types.
/// \tparam V Value constructor argument types.
/// \param pos The insertion position.
/// \param args Arguments to pass to the value constructor.
/// \param args Arguments to forward to the value's constructor.
///
/// \returns An iterator to the inserted value.
///
/// \remarks There is no difference between insert and emplace
/// For trivial value types (floats, ints, bools).
/// for trivial value types (floats, ints, bools).
template <typename U, typename... V>
iterator emplace(const_iterator pos, V&&... args) noexcept
{
@ -570,17 +555,13 @@ namespace toml
"Emplacement type parameter must be one of the basic value types, a toml::table, or a toml::array"
);
return { values.emplace(pos.raw_, new node_of<type>{ std::forward<V>(args)...} ) };
return { values.emplace(pos.raw_, new impl::node_of<type>{ std::forward<V>(args)...} ) };
}
/// \brief Removes the specified node from the array.
///
/// \detail \cpp
/// auto arr = toml::array{
/// 1,
/// 2,
/// 3
/// };
/// auto arr = toml::array{ 1, 2, 3 };
/// std::cout << arr << std::endl;
///
/// arr.erase(arr.cbegin() + 1);
@ -602,12 +583,7 @@ namespace toml
/// \brief Removes the nodes in the range [first, last) from the array.
///
/// \detail \cpp
/// auto arr = toml::array{
/// 1,
/// "bad",
/// "karma"
/// 2,
/// };
/// auto arr = toml::array{ 1, "bad", "karma" 2 };
/// std::cout << arr << std::endl;
///
/// arr.erase(arr.cbegin() + 1, arr.cbegin() + 3);
@ -630,10 +606,7 @@ namespace toml
/// \brief Appends a new value to the end of the array.
///
/// \detail \cpp
/// auto arr = toml::array{
/// 1,
/// 2
/// };
/// auto arr = toml::array{ 1, 2 };
/// arr.push_back(3);
/// arr.push_back(4.0);
/// arr.push_back(array{ 5, "six"sv });
@ -658,10 +631,7 @@ namespace toml
/// \brief Emplaces a new value at the end of the array.
///
/// \detail \cpp
/// auto arr = toml::array{
/// 1,
/// 2
/// };
/// auto arr = toml::array{ 1, 2 };
/// arr.emplace_back<array>(3, "four"sv);
/// std::cout << arr << std::endl;
///
@ -671,7 +641,7 @@ namespace toml
///
/// \tparam U One of the TOML value types.
/// \tparam V Value constructor argument types.
/// \param args Arguments to pass to the value constructor.
/// \param args Arguments to forward to the value's constructor.
///
/// \returns A reference to the newly-constructed value node.
///
@ -686,7 +656,7 @@ namespace toml
"Emplacement type parameter must be one of the basic value types, a toml::table, or a toml::array"
);
auto nde = new node_of<type>{ std::forward<V>(args)... };
auto nde = new impl::node_of<type>{ std::forward<V>(args)... };
values.emplace_back(nde);
return *nde;
}
@ -697,13 +667,45 @@ namespace toml
values.pop_back();
}
/// \brief Gets the node at a specific index.
///
/// \detail \cpp
/// auto arr = toml::array{ 99, "bottles of beer on the wall" };
/// std::cout << R"(node [0] exists: )"sv << !!arr.get(0) << std::endl;
/// std::cout << R"(node [1] exists: )"sv << !!arr.get(1) << std::endl;
/// std::cout << R"(node [2] exists: )"sv << !!arr.get(2) << std::endl;
/// if (auto val = arr.get(0))
/// std::cout << R"(node [0] was an )"sv << val->type() << std::endl;
///
/// // output:
/// // node [0] exists: true
/// // node [1] exists: true
/// // node [2] exists: false
/// // node [0] was an integer
/// \ecpp
///
/// \param index The node's index.
///
/// \returns A pointer to the node at the specified index if one existed, or nullptr.
[[nodiscard]] node* get(size_t index) noexcept
{
return index < values.size() ? values[index].get() : nullptr;
}
/// \brief Gets the node at a specific index (const overload).
///
/// \param index The node's index.
///
/// \returns A pointer to the node at the specified index if one existed, or nullptr.
[[nodiscard]] const node* get(size_t index) const noexcept
{
return index < values.size() ? values[index].get() : nullptr;
}
/// \brief Gets the node at a specific index if it is a particular type.
///
/// \detail \cpp
/// auto arr = toml::array{
/// 42,
/// "is the meaning of life, apparently."sv
/// };
/// auto arr = toml::array{ 42, "is the meaning of life, apparently."sv };
/// if (auto val = arr.get_as<int64_t>(0))
/// std::cout << "node [0] was an integer with value "sv << **val << std::endl;
///
@ -714,11 +716,13 @@ namespace toml
/// \tparam T The node's type.
/// \param index The node's index.
///
/// \returns A pointer to the selected node if it was of the specified type, or nullptr.
/// \returns A pointer to the selected node if it existed and was of the specified type, or nullptr.
template <typename T>
[[nodiscard]] node_of<T>* get_as(size_t index) noexcept
[[nodiscard]] impl::node_of<T>* get_as(size_t index) noexcept
{
return values[index]->as<T>();
if (auto val = get(index))
return val->as<T>();
return nullptr;
}
/// \brief Gets the node at a specific index if it is a particular type (const overload).
@ -726,11 +730,13 @@ namespace toml
/// \tparam T The node's type.
/// \param index The node's index.
///
/// \returns A pointer to the selected node if it was of the specified type, or nullptr.
/// \returns A pointer to the selected node if it existed and was of the specified type, or nullptr.
template <typename T>
[[nodiscard]] const node_of<T>* get_as(size_t index) const noexcept
[[nodiscard]] const impl::node_of<T>* get_as(size_t index) const noexcept
{
return values[index]->as<T>();
if (auto val = get(index))
return val->as<T>();
return nullptr;
}
/// \brief Equality operator.
@ -810,17 +816,7 @@ namespace toml
///
/// \detail \cpp
///
/// auto arr = toml::array{
/// 1,
/// 2,
/// toml::array{
/// 3,
/// 4,
/// toml::array{ 5 }
/// },
/// 6,
/// toml::array{}
/// };
/// auto arr = toml::array{ 1, 2, toml::array{ 3, 4, toml::array{ 5 } }, 6, toml::array{} };
/// std::cout << arr << std::endl;
///
/// arr.flatten();

View File

@ -274,16 +274,13 @@ TOML_POP_WARNINGS
/// \brief The root namespace for all toml++ functions and types.
namespace toml
{
inline namespace literals
{
using namespace std::string_literals;
using namespace std::string_view_literals;
using namespace std::string_literals;
using namespace std::string_view_literals;
[[nodiscard]] TOML_ALWAYS_INLINE
TOML_CONSTEVAL size_t operator"" _sz(unsigned long long n) noexcept
{
return static_cast<size_t>(n);
}
[[nodiscard]] TOML_ALWAYS_INLINE
TOML_CONSTEVAL size_t operator"" _sz(unsigned long long n) noexcept
{
return static_cast<size_t>(n);
}
#if TOML_CHAR_8_STRINGS
@ -328,9 +325,9 @@ namespace toml
integer, ///< The node is a toml::value<int64_t>.
floating_point, ///< The node is a toml::value<double>.
boolean, ///< The node is a toml::value<bool>.
date, ///< The node is a toml::value<toml::date>.
time, ///< The node is a toml::value<toml::time>.
date_time ///< The node is a toml::value<toml::date_time>.
date, ///< The node is a toml::value<date>.
time, ///< The node is a toml::value<time>.
date_time ///< The node is a toml::value<date_time>.
};
#if TOML_LARGE_FILES
@ -599,13 +596,12 @@ namespace toml::impl
// Q: "why not use std::find??"
// A: Because <algorithm> is _huge_ and std::find would be the only thing I used from it.
// I don't want to impose such a heavy burden on users.
// I don't want to impose such a heavy compile-time burden on users.
template <typename T>
inline std::optional<size_t> find(const std::vector<T>& haystack, const T& needle) noexcept
{
const auto end = haystack.size();
for (size_t i = 0; i < end; i++)
for (size_t i = 0, e = haystack.size(); i < e; i++)
if (haystack[i] == needle)
return i;
return {};
@ -658,6 +654,9 @@ namespace toml::impl
template <> struct node_wrapper<time> { using type = value<time>; };
template <> struct node_wrapper<date_time> { using type = value<date_time>; };
template <typename T>
using node_of = typename impl::node_wrapper<T>::type;
template <typename T> struct node_unwrapper { using type = T; };
template <typename T> struct node_unwrapper<value<T>> { using type = T; };
@ -776,39 +775,47 @@ namespace toml::impl
namespace toml
{
/// \brief Helper alias that wraps a type up as it's TOML node equivalent.
template <typename T>
using node_of = typename impl::node_wrapper<T>::type;
/// \brief Metafunction for determining if a type is a toml::table.
template <typename T>
inline constexpr bool is_table = std::is_same_v<impl::remove_cvref_t<T>, table>;
/// \brief Metafunction for determining if a type is a toml::array.
template <typename T>
inline constexpr bool is_array = std::is_same_v<impl::remove_cvref_t<T>, array>;
/// \brief Metafunction for determining if a type is a toml::value<string>.
/// \brief Metafunction for determining if a type is a toml::string or toml::value<toml::string>.
template <typename T>
inline constexpr bool is_string = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<string>>;
/// \brief Metafunction for determining if a type is a toml::value<int64_t>.
inline constexpr bool is_string = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<string>>;
/// \brief Metafunction for determining if a type is an int64_t or toml::value<int64_t>.
template <typename T>
inline constexpr bool is_integer = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<int64_t>>;
/// \brief Metafunction for determining if a type is a toml::value<double>.
inline constexpr bool is_integer = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<int64_t>>;
/// \brief Metafunction for determining if a type is a double or toml::value<double>.
template <typename T>
inline constexpr bool is_floating_point = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<double>>;
/// \brief Metafunction for determining if a type is a toml::value<bool>.
inline constexpr bool is_floating_point = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<double>>;
/// \brief Metafunction for determining if a type is a bool toml::value<bool>.
template <typename T>
inline constexpr bool is_boolean = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<bool>>;
/// \brief Metafunction for determining if a type is a toml::value<toml::date>.
inline constexpr bool is_boolean = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<bool>>;
/// \brief Metafunction for determining if a type is a toml::date or toml::value<date>.
template <typename T>
inline constexpr bool is_date = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<date>>;
/// \brief Metafunction for determining if a type is a toml::value<toml::time>.
inline constexpr bool is_date = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<date>>;
/// \brief Metafunction for determining if a type is a toml::time or toml::value<time>.
template <typename T>
inline constexpr bool is_time = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<time>>;
/// \brief Metafunction for determining if a type is a toml::value<toml::date_time>.
inline constexpr bool is_time = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<time>>;
/// \brief Metafunction for determining if a type is a toml::date_time or toml::value<date_time>.
template <typename T>
inline constexpr bool is_date_time = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<date_time>>;
inline constexpr bool is_date_time = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<date_time>>;
/// \brief Pretty-prints the value of a node_type to a stream.
///
/// \detail \cpp
/// auto arr = toml::array{ 1, 2.0, "3", false };
/// for (size_t i = 0; i < arr.size() i++)
/// std::cout << "Element ["sv << i << "] is: "sv << arr[i].type() << std::endl;
///
/// // output:
/// // Element [0] is: integer
/// // Element [1] is: floating-point
/// // Element [2] is: string
/// // Element [3] is: boolean
/// \ecpp
template <typename CHAR>
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, node_type rhs) TOML_MAY_THROW
{

View File

@ -32,15 +32,15 @@ namespace toml
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
node_of<T>& ref_cast() & noexcept { return *reinterpret_cast<node_of<T>*>(this); }
impl::node_of<T>& ref_cast() & noexcept { return *reinterpret_cast<impl::node_of<T>*>(this); }
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
node_of<T>&& ref_cast() && noexcept { return std::move(*reinterpret_cast<node_of<T>*>(this)); }
impl::node_of<T>&& ref_cast() && noexcept { return std::move(*reinterpret_cast<impl::node_of<T>*>(this)); }
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
const node_of<T>& ref_cast() const & noexcept { return *reinterpret_cast<const node_of<T>*>(this); }
const impl::node_of<T>& ref_cast() const & noexcept { return *reinterpret_cast<const impl::node_of<T>*>(this); }
template <typename N, typename T>
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
@ -158,7 +158,7 @@ namespace toml
/// \returns A pointer to the node as the given type, or nullptr if it was a different type.
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
node_of<T>* as() noexcept
impl::node_of<T>* as() noexcept
{
using type = impl::unwrapped<T>;
static_assert(
@ -180,7 +180,7 @@ namespace toml
/// \brief Gets a pointer to the node as a more specific node type (const overload).
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
const node_of<T>* as() const noexcept
const impl::node_of<T>* as() const noexcept
{
using type = impl::unwrapped<T>;
static_assert(

View File

@ -127,6 +127,10 @@ namespace toml::impl
namespace toml
{
/// \brief A read-only view into a node.
///
/// \warning This type is experimental. Functionality may change radically between versions
/// until I decide that I'm happy with it. Use it at your own risk.
template <typename T>
class node_view final
{
@ -164,7 +168,7 @@ namespace toml
}
template <typename U>
[[nodiscard]] const node_of<U>* as() const noexcept
[[nodiscard]] const impl::node_of<U>* as() const noexcept
{
static_assert(
impl::is_value_or_node<impl::unwrapped<U>>,

View File

@ -3049,13 +3049,21 @@ namespace toml
{
/// \brief Parses a TOML document from a string view.
///
/// \detail \cpp
/// auto tbl = toml::parse("a = 3"sv);
/// std::cout << tbl["a"] << std::endl;
///
/// // output:
/// // 3
/// \ecpp
///
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
/// If you don't have a path (or you have no intention of using paths in diagnostics)
/// then this parameter can safely be left blank.
///
/// \returns A TOML table if exceptions are in use,
/// or a parse_result detailing the parsing outcome if exceptions are disabled.
/// \returns <em>With exceptions:</em> A toml::table. <br>
/// <em>Without exceptions:</em> A toml::parse_result detailing the parsing outcome.
[[nodiscard]]
inline parse_result parse(std::string_view doc, std::string_view source_path = {}) TOML_MAY_THROW
{
@ -3064,60 +3072,99 @@ namespace toml
/// \brief Parses a TOML document from a string view.
///
///
/// \detail \cpp
/// auto tbl = toml::parse("a = 3"sv, "foo.toml");
/// std::cout << tbl["a"] << std::endl;
///
/// // output:
/// // 3
/// \ecpp
///
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
///
/// \returns A TOML table if exceptions are in use,
/// or a parse_result detailing the parsing outcome if exceptions are disabled.
/// \returns <em>With exceptions:</em> A toml::table. <br>
/// <em>Without exceptions:</em> A toml::parse_result detailing the parsing outcome.
[[nodiscard]]
inline parse_result parse(std::string_view doc, std::string&& source_path) TOML_MAY_THROW
{
return impl::parser{ impl::utf8_reader{ doc, std::move(source_path) } };
}
#if defined(__cpp_lib_char8_t)
#if defined(__cpp_lib_char8_t)
/// \brief Parses a TOML document from a string view.
/// \brief Parses a TOML document from a char8_t string view.
///
/// \detail \cpp
/// auto tbl = toml::parse(u8"a = 3"sv);
/// std::cout << tbl["a"] << std::endl;
///
/// // output:
/// // 3
/// \ecpp
///
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
/// If you don't have a path (or you have no intention of using paths in diagnostics)
/// then this parameter can safely be left blank.
///
/// \returns A TOML table if exceptions are in use,
/// or a parse_result detailing the parsing outcome if exceptions are disabled.
/// \returns <em>With exceptions:</em> A toml::table. <br>
/// <em>Without exceptions:</em> A toml::parse_result detailing the parsing outcome.
///
/// \attention This overload is not available if your compiler does not support char8_t-based strings.
[[nodiscard]]
inline parse_result parse(std::u8string_view doc, std::string_view source_path = {}) TOML_MAY_THROW
{
return impl::parser{ impl::utf8_reader{ doc, source_path } };
}
/// \brief Parses a TOML document from a string view.
///
/// \brief Parses a TOML document from a char8_t string view.
///
/// \detail \cpp
/// auto tbl = toml::parse(u8"a = 3"sv, "foo.toml");
/// std::cout << tbl["a"] << std::endl;
///
/// // output:
/// // 3
/// \ecpp
///
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
///
/// \returns A TOML table if exceptions are in use,
/// or a parse_result detailing the parsing outcome if exceptions are disabled.
/// \returns <em>With exceptions:</em> A toml::table. <br>
/// <em>Without exceptions:</em> A toml::parse_result detailing the parsing outcome.
///
/// \attention This overload is not available if your compiler does not support char8_t-based strings.
[[nodiscard]]
inline parse_result parse(std::u8string_view doc, std::string&& source_path) TOML_MAY_THROW
{
return impl::parser{ impl::utf8_reader{ doc, std::move(source_path) } };
}
#endif
#endif // defined(__cpp_lib_char8_t)
/// \brief Parses a TOML document from a stream.
///
/// \detail \cpp
/// std::stringstream ss;
/// ss << "a = 3"sv;
///
/// auto tbl = toml::parse(ss);
/// std::cout << tbl["a"] << std::endl;
///
/// // output:
/// // 3
/// \ecpp
///
/// \tparam CHAR The stream's underlying character type. Must be 1 byte in size.
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
/// If you don't have a path (or you have no intention of using paths in diagnostics)
/// then this parameter can safely be left blank.
///
/// \returns A TOML table if exceptions are in use,
/// or a parse_result detailing the parsing outcome if exceptions are disabled.
/// \returns <em>With exceptions:</em> A toml::table. <br>
/// <em>Without exceptions:</em> A toml::parse_result detailing the parsing outcome.
template <typename CHAR>
[[nodiscard]]
inline parse_result parse(std::basic_istream<CHAR>& doc, std::string_view source_path = {}) TOML_MAY_THROW
@ -3132,12 +3179,23 @@ namespace toml
/// \brief Parses a TOML document from a stream.
///
/// \detail \cpp
/// std::stringstream ss;
/// ss << "a = 3"sv;
///
/// auto tbl = toml::parse(ss, "foo.toml");
/// std::cout << tbl["a"] << std::endl;
///
/// // output:
/// // 3
/// \ecpp
///
/// \tparam CHAR The stream's underlying character type. Must be 1 byte in size.
/// \param doc The TOML document to parse. Must be valid UTF-8.
/// \param source_path The path used to initialize each node's `source().path`.
///
/// \returns A TOML table if exceptions are in use,
/// or a parse_result detailing the parsing outcome if exceptions are disabled.
/// \returns <em>With exceptions:</em> A toml::table. <br>
/// <em>Without exceptions:</em> A toml::parse_result detailing the parsing outcome.
template <typename CHAR>
[[nodiscard]]
inline parse_result parse(std::basic_istream<CHAR>& doc, std::string&& source_path) TOML_MAY_THROW
@ -3152,13 +3210,22 @@ namespace toml
/// \brief Parses a TOML document from a file.
///
/// \detail \cpp
/// #include <fstream>
///
/// toml::parse_result get_foo_toml()
/// {
/// return toml::parse_file("foo.toml");
/// }
/// \ecpp
///
/// \tparam CHAR The path's character type. Must be 1 byte in size.
/// \param file_path The TOML document to parse. Must be valid UTF-8.
///
/// \returns A TOML table if exceptions are in use,
/// or a parse_result detailing the parsing outcome if exceptions are disabled.
/// \returns <em>With exceptions:</em> A toml::table. <br>
/// <em>Without exceptions:</em> A toml::parse_result detailing the parsing outcome.
///
/// \remarks You must `#include <fstream>` to use this function (toml++
/// \attention You must `#include <fstream>` to use this function (toml++
/// does not transitively include it for you).
template <typename CHAR>
inline parse_result parse_file(std::basic_string_view<CHAR> file_path) TOML_MAY_THROW
@ -3178,4 +3245,64 @@ namespace toml
std::string_view{ reinterpret_cast<const char*>(file_path.data()), file_path.length() }
);
}
/// \brief Convenience literal operators for working with TOML++.
///
/// \remark This namespace exists so you can safely hoist the UDL operators into another scope
/// without dragging in everything in the toml namespace.
inline namespace literals
{
/// \brief Parses TOML data from a string.
///
/// \detail \cpp
/// using namespace toml::literals;
///
/// auto tbl = "a = 3"_toml;
/// std::cout << tbl["a"] << std::endl;
///
/// // output:
/// // 3
/// \ecpp
///
/// \param str The string data.
/// \param len The string length.
///
/// \returns <em>With exceptions:</em> A toml::table. <br>
/// <em>Without exceptions:</em> A toml::parse_result detailing the parsing outcome.
[[nodiscard]]
inline parse_result operator"" _toml(const char* str, size_t len) noexcept
{
return parse(std::string_view{ str, len });
}
#if defined(__cpp_lib_char8_t)
/// \brief Parses TOML data from a string.
///
/// \detail \cpp
/// using namespace toml::literals;
///
/// auto tbl = u8"a = 3"_toml;
/// std::cout << tbl["a"] << std::endl;
///
/// // output:
/// // 3
/// \ecpp
///
/// \param str The string data.
/// \param len The string length.
///
/// \returns <em>With exceptions:</em> A toml::table. <br>
/// <em>Without exceptions:</em> A toml::parse_result detailing the parsing outcome.
///
/// \attention This overload is not available if your compiler does not support char8_t-based strings.
[[nodiscard]]
inline parse_result operator"" _toml(const char8_t* str, size_t len) noexcept
{
return parse(std::u8string_view{ str, len });
}
#endif
}
}

View File

@ -148,7 +148,7 @@ namespace toml
/// \brief Constructs a table with one or more initial key-value pairs.
///
/// \detail \cpp
/// auto tbl = toml::table{{ //double braces required :( - see Remarks
/// auto tbl = toml::table{{ // double braces required :( - see remark
/// { "foo", 1 },
/// { "bar", 2.0 },
/// { "kek", "three" }
@ -165,13 +165,13 @@ namespace toml
/// \remarks C++ std::initializer_lists represent their member elements as
/// const even if the list's value type is non-const. This is great for
/// compiler writers, I guess, but pretty annoying for me since
/// TOML key-value pairs are polymorphic. This means that for the
/// human-friendly braced init list syntax to work I can't use
/// TOML key-value pairs are polymorphic (and thus move-only). This means
/// that for the human-friendly braced init list syntax to work I can't use
/// std::initializer_list and must instead invent an annoying proxy type,
/// which means an extra level of nesting.
/// <br><br>
/// See https://en.cppreference.com/w/cpp/utility/initializer_list
/// if you'd like to be more annoyed about this.
/// if you'd like to learn more about this.
template <size_t N>
TOML_NODISCARD_CTOR
explicit table(impl::table_init_pair(&& arr)[N]) noexcept
@ -213,7 +213,6 @@ namespace toml
[[nodiscard]] table* as_table() noexcept override { return this; }
[[nodiscard]] const table* as_table() const noexcept override { return this; }
/// \brief Returns true if this table is an inline table.
///
/// \remarks Runtime-constructed tables (i.e. those not created during
@ -261,9 +260,9 @@ namespace toml
///
/// \returns A node_view.
///
/// \remarks std::map::operator[]'s behaviour of constructing an element at a key if it
/// didn't exist is terribad, so I've deliberately chosen not to emulate that
/// insane bug-factory. This Is Not An Error (tm).
/// \remarks std::map::operator[]'s behaviour of default-constructing a value at a key if it
/// didn't exist is a crazy bug factory so I've deliberately chosen not to emulate it.
/// This Is Not An Error (tm).
///
/// \see toml::node_view
[[nodiscard]] inline node_view<table> operator[] (string_view key) noexcept;
@ -292,6 +291,38 @@ namespace toml
/// \brief Removes all key-value pairs from the table.
void clear() noexcept { values.clear(); }
/// \brief Inserts a new value at a specific key if one did not already exist.
///
/// \detail \cpp
/// auto tbl = toml::table{{
/// { "a", 1 },
/// { "b", 2 },
/// { "c", 3 }
/// }};
/// std::cout << tbl << std::endl;
///
/// for (auto k : { "a", "d" })
/// {
/// auto result = tbl.insert(k, 42);
/// std::cout << "inserted a value with key '"sv << k << "': "sv << result.second << std::endl;
/// }
/// std::cout << tbl << std::endl;
///
/// // output:
/// // { a = 1, b = 2, c = 3 }
/// // inserted a value with key 'a': false
/// // inserted a value with key 'd': true
/// // { a = 1, b = 2, c = 3, d = 42 }
/// \ecpp
///
/// \tparam K toml::string (or a type convertible to it).
/// \tparam V One of the TOML value types (or a type promotable to one).
/// \param key The key at which to insert the new value.
/// \param val The new value to insert.
///
/// \returns A std::pair containing:
/// - An iterator to the insertion position (or the position of the value that prevented insertion)
/// - A boolean indicating if the insertion was successful.
template <typename K, typename V, typename = std::enable_if_t<
std::is_convertible_v<K&&, string_view>
>>
@ -306,6 +337,35 @@ namespace toml
return { ipos, false };
}
/// \brief Inserts a series of key-value pairs into the table.
///
/// \detail \cpp
/// auto tbl = toml::table{{
/// { "a", 1 },
/// { "b", 2 },
/// { "c", 3 }
/// }};
/// std::cout << tbl << std::endl;
///
/// auto kvps = std::array<std::pair<toml::string, int>>{{
/// { "d", 42 },
/// { "a", 43 }
/// }};
/// tbl.insert(kvps.begin(), kvps.end());
/// std::cout << tbl << std::endl;
///
/// // output:
/// // { a = 1, b = 2, c = 3 }
/// // { a = 1, b = 2, c = 3, d = 42 } //"a" already existed
/// \ecpp
///
/// \tparam ITER An InputIterator to a collection of key-value pairs.
/// \param first An iterator to the first value in the input collection.
/// \param last An iterator to one-past-the-last value in the input collection.
///
/// \remarks This function is morally equivalent to calling insert(key, value) for each
/// key-value pair covered by the iterator range, so any values with keys already found in the
/// table will not be replaced.
template <typename ITER, typename = std::enable_if_t<
!std::is_convertible_v<ITER&&, string_view>
>>
@ -322,6 +382,39 @@ namespace toml
}
}
/// \brief Inserts or assigns a value at a specific key.
///
/// \detail \cpp
/// auto tbl = toml::table{{
/// { "a", 1 },
/// { "b", 2 },
/// { "c", 3 }
/// }};
/// std::cout << tbl << std::endl;
///
/// for (auto k : { "a", "d" })
/// {
/// auto result = tbl.insert_or_assign(k, 42);
/// std::cout << "value at key '"sv << k
/// << "' was "sv << (result.second ? "inserted"sv : "assigned"sv) << std::endl;
/// }
/// std::cout << tbl << std::endl;
///
/// // output:
/// // { a = 1, b = 2, c = 3 }
/// // value at key 'a' was assigned
/// // value at key 'd' was inserted
/// // { a = 42, b = 2, c = 3, d = 42 }
/// \ecpp
///
/// \tparam K toml::string (or a type convertible to it).
/// \tparam V One of the TOML value types (or a type promotable to one).
/// \param key The key at which to insert or assign the value.
/// \param val The value to insert/assign.
///
/// \returns A std::pair containing:
/// - An iterator to the value's position
/// - A boolean containing `true` if the value was inserted, `false` if it was assigned.
template <typename K, typename V>
std::pair<iterator, bool> insert_or_assign(K&& key, V&& val) noexcept
{
@ -338,6 +431,42 @@ namespace toml
}
}
/// \brief Emplaces a new value at a specific key if one did not already exist.
///
/// \detail \cpp
/// auto tbl = toml::table{{
/// { "a", 1 },
/// { "b", 2 },
/// { "c", 3 }
/// }};
/// std::cout << tbl << std::endl;
///
/// for (auto k : { "a", "d" })
/// {
/// // add a string using std::string's substring constructor
/// auto result = tbl.emplace<std::string>(k, "this is not a drill"sv, 14, 5);
/// std::cout << "emplaced a value with key '"sv << k << "': "sv << result.second << std::endl;
/// }
/// std::cout << tbl << std::endl;
///
/// // output:
/// // { a = 1, b = 2, c = 3 }
/// // emplaced a value with key 'a': false
/// // emplaced a value with key 'd': true
/// // { a = 1, b = 2, c = 3, d = "drill" }
/// \ecpp
///
/// \tparam U One of the TOML node or value types.
/// \tparam K toml::string (or a type convertible to it).
/// \tparam V Value constructor argument types.
/// \param key The key at which to emplace the new value.
/// \param args Arguments to forward to the value's constructor.
///
/// \returns A std::pair containing:
/// - An iterator to the emplacement position (or the position of the value that prevented emplacement)
/// - A boolean indicating if the emplacement was successful.
///
/// \remark There is no difference between insert and emplace for trivial value types (floats, ints, bools).
template <typename U, typename K, typename... V>
std::pair<iterator, bool> emplace(K&& key, V&&... args) noexcept
{
@ -353,7 +482,7 @@ namespace toml
ipos = values.emplace_hint(
ipos,
std::forward<K>(key),
new node_of<type>{ std::forward<V>(args)... }
new impl::node_of<type>{ std::forward<V>(args)... }
);
return { ipos, true };
}
@ -510,7 +639,38 @@ namespace toml
public:
/// \brief Gets the node at a specific key.
///
/// \detail \cpp
/// auto tbl = toml::table{{
/// { "a", 42, },
/// { "b", "is the meaning of life, apparently." }
/// }};
/// std::cout << R"(node ["a"] exists: )"sv << !!arr.get("a") << std::endl;
/// std::cout << R"(node ["b"] exists: )"sv << !!arr.get("b") << std::endl;
/// std::cout << R"(node ["c"] exists: )"sv << !!arr.get("c") << std::endl;
/// if (auto val = arr.get("a"))
/// std::cout << R"(node ["a"] was an )"sv << val->type() << std::endl;
///
/// // output:
/// // node ["a"] exists: true
/// // node ["b"] exists: true
/// // node ["c"] exists: false
/// // node ["a"] was an integer
/// \ecpp
///
/// \tparam T The node's type.
/// \param key The node's key.
///
/// \returns A pointer to the node at the specified key, or nullptr.
[[nodiscard]] node* get(string_view key) noexcept { return do_get(values, key); }
/// \brief Gets the node at a specific key (const overload).
///
/// \tparam T The node's type.
/// \param key The node's key.
///
/// \returns A pointer to the node at the specified key, or nullptr.
[[nodiscard]] const node* get(string_view key) const noexcept { return do_get(values, key); }
[[nodiscard]] iterator find(string_view key) noexcept { return { values.find(key) }; }
@ -524,7 +684,7 @@ namespace toml
/// { "b", "is the meaning of life, apparently." }
/// }};
/// if (auto val = arr.get_as<int64_t>("a"))
/// std::cout << node [\"a\"] was an integer with value "sv << **val << std::endl;
/// std::cout << R"(node ["a"] was an integer with value )"sv << **val << std::endl;
///
/// // output:
/// // node ["a"] was an integer with value 42
@ -533,18 +693,18 @@ namespace toml
/// \tparam T The node's type.
/// \param key The node's key.
///
/// \returns A pointer to the selected node if it was of the specified type, or nullptr.
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
template <typename T>
[[nodiscard]] node_of<T>* get_as(string_view key) noexcept { return do_get_as<T>(values, key); }
[[nodiscard]] impl::node_of<T>* get_as(string_view key) noexcept { return do_get_as<T>(values, key); }
/// \brief Gets the node at a specific key if it is a particular type (const overload).
///
/// \tparam T The node's type.
/// \param key The node's key.
///
/// \returns A pointer to the selected node if it was of the specified type, or nullptr.
/// \returns A pointer to the node at the specified key if it was of the given type, or nullptr.
template <typename T>
[[nodiscard]] const node_of<T>* get_as(string_view key) const noexcept { return do_get_as<T>(values, key); }
[[nodiscard]] const impl::node_of<T>* get_as(string_view key) const noexcept { return do_get_as<T>(values, key); }
/// \brief Returns true if the table contains a node at the given key.
[[nodiscard]] bool contains(string_view key) const noexcept { return do_contains(values, key); }

View File

@ -44,7 +44,7 @@ namespace toml
/// \brief Constructs a toml value.
///
/// \tparam U Constructor argument types.
/// \param args Variadic list of arguments that are forwarded to the internal value's constructor.
/// \param args Arguments to forward to the internal value's constructor.
template <typename... U>
TOML_NODISCARD_CTOR
explicit value(U&&... args) TOML_MAY_THROW_UNLESS(std::is_nothrow_constructible_v<T, U &&...>)

View File

@ -16,11 +16,54 @@ import bs4 as soup
_inlineNamespaces = [
inline_namespaces = [
"toml::literals",
]
_inlineNamespaceExplainer = 'All members of this namespace are automatically members of the parent namespace. ' \
inline_namespace_explainer = 'All members of this namespace are automatically members of the parent namespace. ' \
+ 'It does not require an explicit \'using\' statement.'
type_names = [
'table',
'array',
'value',
'date',
'time',
'date_time',
'string',
'string_view',
'parse_result',
'parse_error',
'size_t',
'uint8_t',
'uint16_t',
'uint32_t',
'uint64_t',
'int8_t',
'int16_t',
'int32_t',
'int64_t',
'ptrdiff_t',
'intptr_t',
'uintptr_t',
'exception',
'iterator',
'const_iterator',
'int',
'long',
'short',
'signed',
'unsigned',
'float',
'double',
'bool',
'pair',
'tuple',
]
all_namespaces = [
'std',
'toml',
'literals',
'impl'
]
@ -28,6 +71,7 @@ def is_tool(name):
return shutil.which(name) is not None
def is_collection(val):
if isinstance(val, (list, tuple, dict, set)):
return True
@ -35,6 +79,14 @@ def is_collection(val):
def read_all_text_from_file(path):
print("Reading {}".format(path))
with open(path, 'r', encoding='utf-8') as file:
text = file.read()
return text
def get_all_files(dir, all=None, any=None):
files = [f for f in [path.join(dir, f) for f in os.listdir(dir)] if path.isfile(f)]
if (files and all is not None):
@ -91,6 +143,7 @@ class HTMLDocument(object):
return tag
def find_all_from_sections(self, name=None, select=None, section=None, **kwargs):
tags = []
sectionArgs = { }
@ -124,7 +177,7 @@ def html_find_parent(tag,name,cutoff=None):
def html_replace_tag(tag,str):
doc = soup.BeautifulSoup(str, 'html5lib')
newTags = None
if (len(doc.body.contents) > 0):
if (len(doc.body.contents) > 0):
newTags = [f for f in doc.body.contents]
newTags = [f.extract() for f in newTags]
prev = tag
@ -355,7 +408,7 @@ class ModifiersFix2(ModifiersFixBase):
# base type for applying inline namespace annotations.
class InlineNamespaceFixBase(object):
_namespaceFiles = ['namespace{}.html'.format(ns.lower().replace('::','_1_1')) for ns in _inlineNamespaces]
_namespaceFiles = ['namespace{}.html'.format(ns.lower().replace('::','_1_1')) for ns in inline_namespaces]
@ -368,7 +421,7 @@ class InlineNamespaceFix1(InlineNamespaceFixBase):
__allowedFiles = ['annotated.html', 'namespaces.html']
def __call__(self, file, doc):
global _inlineNamespaceExplainer
global inline_namespace_explainer
changed = False
if (file in self.__allowedFiles):
anchors = []
@ -383,7 +436,7 @@ class InlineNamespaceFix1(InlineNamespaceFixBase):
doc.new_tag('span',
after=anchor,
string='inline',
title=_inlineNamespaceExplainer,
title=inline_namespace_explainer,
class_='m-label m-info m-flat tpp-injected tpp-inline-namespace'
)
anchor.insert_after(' ')
@ -400,7 +453,7 @@ class InlineNamespaceFix1(InlineNamespaceFixBase):
class InlineNamespaceFix2(InlineNamespaceFixBase):
def __call__(self, file, doc):
global _inlineNamespaceExplainer
global inline_namespace_explainer
changed = False
if (file in self._namespaceFiles):
h1 = doc.body.find('h1')
@ -409,7 +462,7 @@ class InlineNamespaceFix2(InlineNamespaceFixBase):
tag = doc.new_tag('span',
parent=h1,
string='inline',
title=_inlineNamespaceExplainer,
title=inline_namespace_explainer,
class_='m-label m-info tpp-injected tpp-inline-namespace'
)
tag.insert_before(' ')
@ -426,7 +479,7 @@ class InlineNamespaceFix2(InlineNamespaceFixBase):
class InlineNamespaceFix3(InlineNamespaceFixBase):
def __call__(self, file, doc):
global _inlineNamespaceExplainer
global inline_namespace_explainer
anchors = doc.find_all_from_sections('a', section='namespaces')
changed = False
for anchor in anchors:
@ -440,7 +493,7 @@ class InlineNamespaceFix3(InlineNamespaceFixBase):
doc.new_tag('span',
after=anchor,
string='inline',
title=_inlineNamespaceExplainer,
title=inline_namespace_explainer,
class_='m-label m-info m-flat tpp-injected tpp-inline-namespace'
)
anchor.insert_after(' ')
@ -453,6 +506,44 @@ class InlineNamespaceFix3(InlineNamespaceFixBase):
# adds some additional colouring to the syntax highlighting in code blocks.
class SyntaxHighlightingFix(object):
def __call__(self, file, doc):
global type_names
global all_namespaces
code_blocks = doc.body('pre', class_='m-code')
changed = False
for code_block in code_blocks:
names = code_block('span', class_='n')
# namespaces
for name in names:
if (name.string is None or name.string not in all_namespaces):
continue
next = name.next_sibling
if (next is None or next.string is None or next.string != '::'):
continue
next.extract()
name.string.replace_with(name.string + '::')
name['class'] = 'ns'
changed = True
# user types and typedefs
names += code_block('span', class_='kt')
for name in names:
if (name.string is not None and name.string in type_names):
name['class'] = 'ut'
changed = True
return changed
#=======================================================================================================================
# adds links to external sources where appropriate
class ExtDocLinksFix(object):
__types = [
@ -497,12 +588,12 @@ class ExtDocLinksFix(object):
(r'std::(?:basic_|w|u8)?string_views?', 'https://en.cppreference.com/w/cpp/string/basic_string_view'),
(r'std::(?:basic_|w|u8)?strings?', 'https://en.cppreference.com/w/cpp/string/basic_string'),
(r'(?:<|&lt;)fstream(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/fstream'),
(r'(?:<|&lt;)sstream(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/sstream'),
(r'(?:<|&lt;)iostream(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/iostream'),
(r'(?:<|&lt;)iosfwd(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/iosfwd'),
(r'(?:<|&lt;)string(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/string'),
(r'(?:<|&lt;)string_view(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/string_view'),
(r'\s(?:<|&lt;)fstream(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/fstream'),
(r'\s(?:<|&lt;)sstream(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/sstream'),
(r'\s(?:<|&lt;)iostream(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/iostream'),
(r'\s(?:<|&lt;)iosfwd(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/iosfwd'),
(r'\s(?:<|&lt;)string(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/string'),
(r'\s(?:<|&lt;)string_view(?:>|&gt;)', 'https://en.cppreference.com/w/cpp/header/string_view'),
(r'char(?:8|16|32)_ts?', 'https://en.cppreference.com/w/cpp/language/types'),
@ -542,30 +633,42 @@ class ExtDocLinksFix(object):
(r'(?:Legacy)?BidirectionalIterators?', 'https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator'),
(r'(?:Legacy)?RandomAccessIterators?', 'https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator'),
(r'(?:Legacy)?ContiguousIterators?', 'https://en.cppreference.com/w/cpp/named_req/ContiguousIterator'),
(r'(?:Legacy)?Iterators?', 'https://en.cppreference.com/w/cpp/named_req/Iterator')
(r'(?:Legacy)?Iterators?', 'https://en.cppreference.com/w/cpp/named_req/Iterator'),
# toml-specific
(r'toml::values?', 'classtoml_1_1value.html'),
(r'(toml::)?date_times?', 'structtoml_1_1date__time.html'),
(r'(toml::)?time', 'structtoml_1_1time.html'),
(r'(toml::)?date', 'structtoml_1_1date.html')
]
__allowedNames = ['dd', 'p', 'dt', 'h3', 'td']
def __init__(self):
self.__expressions = []
for type, uri in self.__types:
self.__expressions.append((re.compile(type+'(?!</a>)'), uri))
self.__expressions.append((re.compile(type), uri))
@classmethod
def __substitute(cls, m, uri):
return r'<a href="{}" class="m-doc tpp-injected tpp-external" target="_blank">{}</a>'.format(
external = uri.startswith('http')
return r'<a href="{}" class="m-doc tpp-injected{}"{}>{}</a>'.format(
uri,
m.group(0)
' tpp-external' if external else '',
' target="_blank"' if external else '',
m.group(0),
)
def __process_tag(self, tag):
for expr, uri in self.__expressions:
for descendant in tag.descendants:
if (not isinstance(descendant, soup.NavigableString) or html_find_parent(descendant, 'a', tag) is not None):
continue
for descendant in tag.descendants:
if (not isinstance(descendant, soup.NavigableString) or html_find_parent(descendant, 'a', tag) is not None):
continue
for expr, uri in self.__expressions:
replacer = RegexReplacer(expr, lambda m: self.__substitute(m, uri), html.escape(str(descendant), quote=False))
if (replacer):
html_replace_tag(descendant, str(replacer))
repl_str = str(replacer)
begins_with_ws = len(repl_str) > 0 and repl_str[:1].isspace()
new_tag = html_replace_tag(descendant, repl_str)[0]
if (begins_with_ws and new_tag.string is not None and not new_tag.string[:1].isspace()):
new_tag.insert_before(' ')
return True
return False
@ -695,6 +798,35 @@ def run_python_script(script_path, *args):
def preprocess_xml(xml_dir):
# fix value not knowing it's a child of node
toml_value_path = path.join(xml_dir, 'classtoml_1_1value.xml')
toml_value_text = read_all_text_from_file(toml_value_path)
toml_value_search_string = '<compoundname>toml::value</compoundname>'
toml_value_insert_pos = toml_value_text.find(toml_value_search_string)
if (toml_value_insert_pos != -1):
toml_value_insert_pos += len(toml_value_search_string)
toml_value_text = toml_value_text[:toml_value_insert_pos] \
+ '\n <basecompoundref refid="classtoml_1_1node" prot="public" virt="non-virtual">toml::node</basecompoundref>' \
+ toml_value_text[toml_value_insert_pos:]
with open(toml_value_path,'w', encoding='utf-8', newline='\n') as output_file:
print(toml_value_text, file=output_file)
# fix node not knowing it has value as a child
toml_node_path = path.join(xml_dir, 'classtoml_1_1node.xml')
toml_node_text = read_all_text_from_file(toml_node_path)
toml_node_search_string = '<compoundname>toml::node</compoundname>'
toml_node_insert_pos = toml_node_text.find(toml_node_search_string)
if (toml_node_insert_pos != -1):
toml_node_insert_pos += len(toml_node_search_string)
toml_node_text = toml_node_text[:toml_node_insert_pos] \
+ '\n <derivedcompoundref refid="classtoml_1_1value" prot="public" virt="non-virtual">toml::value</derivedcompoundref>' \
+ toml_node_text[toml_node_insert_pos:]
with open(toml_node_path,'w', encoding='utf-8', newline='\n') as output_file:
print(toml_node_text, file=output_file)
def main():
global _threadError
@ -710,21 +842,22 @@ def main():
delete_directory(xml_dir)
delete_directory(html_dir)
# run doxygen (via m.css)
run_python_script(doxygen, path.join(docs_dir, 'Doxyfile-mcss'))
# run doxygen
subprocess.check_call( ['doxygen', 'Doxyfile'], shell=True, cwd=docs_dir )
# clean up xml and tmp files
# fix some shit that's broken in the xml
preprocess_xml(xml_dir)
# run doxygen.py (m.css)
run_python_script(doxygen, path.join(docs_dir, 'Doxyfile-mcss'), '--no-doxygen')
# delete xml
delete_directory(xml_dir)
#for file in get_all_files(cwd, '*.tmp'):
# try:
# print('Deleting {}'.format(file))
# os.remove(file)
# except Exception as e:
# fatal_error(e)
# post-process html files
fixes = [
CustomTagsFix()
, SyntaxHighlightingFix()
# , NavBarFix()
, IndexHrefFix()
, ModifiersFix1()

View File

@ -122,7 +122,8 @@ def main():
preamble = []
preamble.append('''
toml++ v{}
https://github.com/marzer/tomlplusplus'''.format('.'.join(str(x) for x in library_version)))
https://github.com/marzer/tomlplusplus
SPDX-License-Identifier: MIT'''.format('.'.join(str(x) for x in library_version)))
preamble.append('''
- THIS FILE WAS ASSEMBLED FROM MULTIPLE HEADER FILES BY A SCRIPT - PLEASE DON'T EDIT IT DIRECTLY -

113
toml.hpp
View File

@ -2,6 +2,7 @@
//
// toml++ v0.1.0
// https://github.com/marzer/tomlplusplus
// SPDX-License-Identifier: MIT
//
//----------------------------------------------------------------------------------------------------------------------
//
@ -37,8 +38,6 @@
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// SPDX-License-Identifier: MIT
//
//----------------------------------------------------------------------------------------------------------------------
//
// UTF-8 decoding is performed using a derivative of Bjoern Hoehrmann's 'Flexible and Economical UTF-8 Decoder'
@ -339,16 +338,13 @@ TOML_POP_WARNINGS
namespace toml
{
inline namespace literals
{
using namespace std::string_literals;
using namespace std::string_view_literals;
using namespace std::string_literals;
using namespace std::string_view_literals;
[[nodiscard]] TOML_ALWAYS_INLINE
TOML_CONSTEVAL size_t operator"" _sz(unsigned long long n) noexcept
{
return static_cast<size_t>(n);
}
[[nodiscard]] TOML_ALWAYS_INLINE
TOML_CONSTEVAL size_t operator"" _sz(unsigned long long n) noexcept
{
return static_cast<size_t>(n);
}
#if TOML_CHAR_8_STRINGS
@ -581,13 +577,12 @@ namespace toml::impl
// Q: "why not use std::find??"
// A: Because <algorithm> is _huge_ and std::find would be the only thing I used from it.
// I don't want to impose such a heavy burden on users.
// I don't want to impose such a heavy compile-time burden on users.
template <typename T>
inline std::optional<size_t> find(const std::vector<T>& haystack, const T& needle) noexcept
{
const auto end = haystack.size();
for (size_t i = 0; i < end; i++)
for (size_t i = 0, e = haystack.size(); i < e; i++)
if (haystack[i] == needle)
return i;
return {};
@ -640,6 +635,9 @@ namespace toml::impl
template <> struct node_wrapper<time> { using type = value<time>; };
template <> struct node_wrapper<date_time> { using type = value<date_time>; };
template <typename T>
using node_of = typename impl::node_wrapper<T>::type;
template <typename T> struct node_unwrapper { using type = T; };
template <typename T> struct node_unwrapper<value<T>> { using type = T; };
@ -757,27 +755,24 @@ namespace toml::impl
namespace toml
{
template <typename T>
using node_of = typename impl::node_wrapper<T>::type;
template <typename T>
inline constexpr bool is_table = std::is_same_v<impl::remove_cvref_t<T>, table>;
template <typename T>
inline constexpr bool is_array = std::is_same_v<impl::remove_cvref_t<T>, array>;
template <typename T>
inline constexpr bool is_string = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<string>>;
inline constexpr bool is_string = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<string>>;
template <typename T>
inline constexpr bool is_integer = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<int64_t>>;
inline constexpr bool is_integer = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<int64_t>>;
template <typename T>
inline constexpr bool is_floating_point = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<double>>;
inline constexpr bool is_floating_point = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<double>>;
template <typename T>
inline constexpr bool is_boolean = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<bool>>;
inline constexpr bool is_boolean = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<bool>>;
template <typename T>
inline constexpr bool is_date = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<date>>;
inline constexpr bool is_date = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<date>>;
template <typename T>
inline constexpr bool is_time = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<time>>;
inline constexpr bool is_time = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<time>>;
template <typename T>
inline constexpr bool is_date_time = std::is_same_v<node_of<impl::remove_cvref_t<T>>, value<date_time>>;
inline constexpr bool is_date_time = std::is_same_v<impl::node_of<impl::remove_cvref_t<T>>, value<date_time>>;
template <typename CHAR>
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, node_type rhs) TOML_MAY_THROW
@ -1299,15 +1294,15 @@ namespace toml
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
node_of<T>& ref_cast() & noexcept { return *reinterpret_cast<node_of<T>*>(this); }
impl::node_of<T>& ref_cast() & noexcept { return *reinterpret_cast<impl::node_of<T>*>(this); }
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
node_of<T>&& ref_cast() && noexcept { return std::move(*reinterpret_cast<node_of<T>*>(this)); }
impl::node_of<T>&& ref_cast() && noexcept { return std::move(*reinterpret_cast<impl::node_of<T>*>(this)); }
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
const node_of<T>& ref_cast() const & noexcept { return *reinterpret_cast<const node_of<T>*>(this); }
const impl::node_of<T>& ref_cast() const & noexcept { return *reinterpret_cast<const impl::node_of<T>*>(this); }
template <typename N, typename T>
using ref_cast_type = decltype(std::declval<N>().template ref_cast<T>());
@ -1375,7 +1370,7 @@ namespace toml
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
node_of<T>* as() noexcept
impl::node_of<T>* as() noexcept
{
using type = impl::unwrapped<T>;
static_assert(
@ -1396,7 +1391,7 @@ namespace toml
template <typename T>
[[nodiscard]] TOML_ALWAYS_INLINE
const node_of<T>* as() const noexcept
const impl::node_of<T>* as() const noexcept
{
using type = impl::unwrapped<T>;
static_assert(
@ -2160,7 +2155,7 @@ namespace toml
"Emplacement type parameter must be one of the basic value types, a toml::table, or a toml::array"
);
return { values.emplace(pos.raw_, new node_of<type>{ std::forward<V>(args)...} ) };
return { values.emplace(pos.raw_, new impl::node_of<type>{ std::forward<V>(args)...} ) };
}
iterator erase(const_iterator pos) noexcept
@ -2190,7 +2185,7 @@ namespace toml
"Emplacement type parameter must be one of the basic value types, a toml::table, or a toml::array"
);
auto nde = new node_of<type>{ std::forward<V>(args)... };
auto nde = new impl::node_of<type>{ std::forward<V>(args)... };
values.emplace_back(nde);
return *nde;
}
@ -2200,16 +2195,30 @@ namespace toml
values.pop_back();
}
template <typename T>
[[nodiscard]] node_of<T>* get_as(size_t index) noexcept
[[nodiscard]] node* get(size_t index) noexcept
{
return values[index]->as<T>();
return index < values.size() ? values[index].get() : nullptr;
}
[[nodiscard]] const node* get(size_t index) const noexcept
{
return index < values.size() ? values[index].get() : nullptr;
}
template <typename T>
[[nodiscard]] const node_of<T>* get_as(size_t index) const noexcept
[[nodiscard]] impl::node_of<T>* get_as(size_t index) noexcept
{
return values[index]->as<T>();
if (auto val = get(index))
return val->as<T>();
return nullptr;
}
template <typename T>
[[nodiscard]] const impl::node_of<T>* get_as(size_t index) const noexcept
{
if (auto val = get(index))
return val->as<T>();
return nullptr;
}
[[nodiscard]] friend bool operator == (const array& lhs, const array& rhs) noexcept
@ -2567,7 +2576,7 @@ namespace toml
ipos = values.emplace_hint(
ipos,
std::forward<K>(key),
new node_of<type>{ std::forward<V>(args)... }
new impl::node_of<type>{ std::forward<V>(args)... }
);
return { ipos, true };
}
@ -2641,10 +2650,10 @@ namespace toml
[[nodiscard]] const_iterator find(string_view key) const noexcept { return { values.find(key) }; }
template <typename T>
[[nodiscard]] node_of<T>* get_as(string_view key) noexcept { return do_get_as<T>(values, key); }
[[nodiscard]] impl::node_of<T>* get_as(string_view key) noexcept { return do_get_as<T>(values, key); }
template <typename T>
[[nodiscard]] const node_of<T>* get_as(string_view key) const noexcept { return do_get_as<T>(values, key); }
[[nodiscard]] const impl::node_of<T>* get_as(string_view key) const noexcept { return do_get_as<T>(values, key); }
[[nodiscard]] bool contains(string_view key) const noexcept { return do_contains(values, key); }
[[nodiscard]] friend bool operator == (const table& lhs, const table& rhs) noexcept
{
@ -2850,7 +2859,7 @@ namespace toml
}
template <typename U>
[[nodiscard]] const node_of<U>* as() const noexcept
[[nodiscard]] const impl::node_of<U>* as() const noexcept
{
static_assert(
impl::is_value_or_node<impl::unwrapped<U>>,
@ -7575,7 +7584,7 @@ namespace toml
return impl::parser{ impl::utf8_reader{ doc, std::move(source_path) } };
}
#if defined(__cpp_lib_char8_t)
#if defined(__cpp_lib_char8_t)
[[nodiscard]]
inline parse_result parse(std::u8string_view doc, std::string_view source_path = {}) TOML_MAY_THROW
@ -7589,7 +7598,7 @@ namespace toml
return impl::parser{ impl::utf8_reader{ doc, std::move(source_path) } };
}
#endif
#endif // defined(__cpp_lib_char8_t)
template <typename CHAR>
[[nodiscard]]
@ -7633,6 +7642,26 @@ namespace toml
std::string_view{ reinterpret_cast<const char*>(file_path.data()), file_path.length() }
);
}
inline namespace literals
{
[[nodiscard]]
inline parse_result operator"" _toml(const char* str, size_t len) noexcept
{
return parse(std::string_view{ str, len });
}
#if defined(__cpp_lib_char8_t)
[[nodiscard]]
inline parse_result operator"" _toml(const char8_t* str, size_t len) noexcept
{
return parse(std::u8string_view{ str, len });
}
#endif
}
}
#pragma endregion