Skip to content

Commit

Permalink
renamed table proxy pair members to first and second to match STL (
Browse files Browse the repository at this point in the history
…closes #30)

also:
- implemented `table_iterator::operator -> ()` (closes #29)
- added `array::resize()` and `array::truncate()` (closes #33)
- refactored BOM handling to make static analyzer happy (closes #34)
- added `array::capacity()`, `array::shrink_to_fit()`, `array::max_size()`
- implemented non-const -> const conversion for table and array iterators
  • Loading branch information
marzer committed May 23, 2020
1 parent 983e229 commit 289c95c
Show file tree
Hide file tree
Showing 14 changed files with 360 additions and 121 deletions.
2 changes: 1 addition & 1 deletion examples/simple_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ int main(int argc, char** argv)
try
{
const auto tbl = toml::parse(file, std::move(path));
//std::cout << tbl << std::endl;
std::cout << tbl << std::endl;
}
catch (const toml::parse_error& err)
{
Expand Down
2 changes: 1 addition & 1 deletion examples/toml_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ int main(int argc, char** argv)
new_node = &(*tree.back()->ref<toml::table>().insert_or_assign(
rand_string(rand<size_t>(1u, 4u), '-'),
std::forward<decltype(obj)>(obj)
).first).value;
).first).second;

if constexpr (toml::is_array<decltype(obj)> || toml::is_table<decltype(obj)>)
{
Expand Down
1 change: 1 addition & 0 deletions include/toml++/toml.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
#undef TOML_ABI_NAMESPACE_START
#undef TOML_ABI_NAMESPACE_END
#undef TOML_PARSER_TYPENAME
#undef TOML_LAUNDER
#endif

/// \mainpage toml++
Expand Down
95 changes: 85 additions & 10 deletions include/toml++/toml_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ namespace toml::impl
class array_iterator final
{
private:
friend class toml::array;
friend class ::toml::array;

using raw_iterator = std::conditional_t<
IsConst,
std::vector<std::unique_ptr<node>>::const_iterator,
std::vector<std::unique_ptr<node>>::iterator
>;
using raw_mutable_iterator = std::vector<std::unique_ptr<node>>::iterator;
using raw_const_iterator = std::vector<std::unique_ptr<node>>::const_iterator;
using raw_iterator = std::conditional_t<IsConst, raw_const_iterator, raw_mutable_iterator>;

mutable raw_iterator raw_;

array_iterator(const raw_iterator& raw) noexcept
array_iterator(raw_mutable_iterator raw) noexcept
: raw_{ raw }
{}

array_iterator(raw_iterator&& raw) noexcept
: raw_{ std::move(raw) }
template <bool C = IsConst, typename = std::enable_if_t<C>>
TOML_NODISCARD_CTOR
array_iterator(raw_const_iterator raw) noexcept
: raw_{ raw }
{}

public:
Expand All @@ -41,6 +41,8 @@ namespace toml::impl
using difference_type = ptrdiff_t;

array_iterator() noexcept = default;
array_iterator(const array_iterator&) noexcept = default;
array_iterator& operator = (const array_iterator&) noexcept = default;

array_iterator& operator++() noexcept // ++pre
{
Expand Down Expand Up @@ -157,6 +159,13 @@ namespace toml::impl
{
return *(raw_ + idx)->get();
}

template <bool C = IsConst, typename = std::enable_if_t<!C>>
[[nodiscard]]
operator array_iterator<true>() const noexcept
{
return array_iterator<true>{ raw_ };
}
};

template <typename T>
Expand Down Expand Up @@ -405,6 +414,13 @@ namespace toml
/// \brief Removes all nodes from the array.
void clear() noexcept;

/// \brief Returns the maximum number of nodes that can be stored in an array on the current platform.
[[nodiscard]] size_t max_size() const noexcept;
/// \brief Returns the current max number of nodes that may be held in the array's internal storage.
[[nodiscard]] size_t capacity() const noexcept;
/// \brief Requests the removal of any unused internal storage capacity.
void shrink_to_fit();

/// \brief Inserts a new node at a specific position in the array.
///
/// \detail \cpp
Expand Down Expand Up @@ -510,7 +526,7 @@ namespace toml

/// \brief Inserts a range of values into the array at a specific position.
///
/// \tparam U One of the TOML node or value types (or a type promotable to one).
/// \tparam U One of the TOML value types (or a type promotable to one).
/// \param pos The insertion position.
/// \param ilist An initializer list containing the values to be inserted.
///
Expand Down Expand Up @@ -613,6 +629,65 @@ namespace toml
/// \returns Iterator to the first node immediately following the last removed node.
iterator erase(const_iterator first, const_iterator last) noexcept;


/// \brief Resizes the array.
///
/// \detail \cpp
/// auto arr = toml::array{ 1, 2, 3 };
/// std::cout << arr << std::endl;
///
/// arr.resize(6, 42);
/// std::cout << arr << std::endl;
///
/// arr.resize(2, 0);
/// std::cout << arr << std::endl;
///
/// \ecpp
///
/// \out
/// [1, 2, 3]
/// [1, 2, 3, 42, 42, 42]
/// [1, 2]
/// \eout
///
/// \tparam U One of the TOML value types (or a type promotable to one).
///
/// \param new_size New number of elements the array will have.
/// \param default_init_val The value used to initialize new elements if the array needs to grow.
template <typename U>
void resize(size_t new_size, U&& default_init_val) noexcept
{
if (!new_size)
values.clear();
else if (new_size < values.size())
values.resize(new_size);
else if (new_size > values.size())
insert(cend(), new_size - values.size(), std::forward<U>(default_init_val));
}

/// \brief Shrinks the array to the given size.
///
/// \detail \cpp
/// auto arr = toml::array{ 1, 2, 3 };
/// std::cout << arr << std::endl;
///
/// arr.truncate(5); // no-op
/// std::cout << arr << std::endl;
///
/// arr.truncate(1);
/// std::cout << arr << std::endl;
///
/// \ecpp
///
/// \out
/// [1, 2, 3]
/// [1, 2, 3]
/// [1]
/// \eout
///
/// \remarks Does nothing if the requested size is larger than or equal to the current size.
void truncate(size_t new_size);

/// \brief Appends a new value to the end of the array.
///
/// \detail \cpp
Expand Down
11 changes: 11 additions & 0 deletions include/toml++/toml_array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ namespace toml
TOML_EXTERNAL_LINKAGE void array::reserve(size_t new_capacity) { values.reserve(new_capacity); }
TOML_EXTERNAL_LINKAGE void array::clear() noexcept { values.clear(); }

TOML_EXTERNAL_LINKAGE size_t array::max_size() const noexcept { return values.max_size(); }
TOML_EXTERNAL_LINKAGE size_t array::capacity() const noexcept { return values.capacity(); }
TOML_EXTERNAL_LINKAGE void array::shrink_to_fit() { values.shrink_to_fit(); }

TOML_EXTERNAL_LINKAGE
void array::truncate(size_t new_size)
{
if (new_size < values.size())
values.resize(new_size);
}

TOML_EXTERNAL_LINKAGE
array::iterator array::erase(const_iterator pos) noexcept
{
Expand Down
6 changes: 6 additions & 0 deletions include/toml++/toml_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ TOML_POP_WARNINGS
#error toml++ requires implementation support to use char8_t strings, but yours does not provide it.
#endif

#ifdef __cpp_lib_launder
#define TOML_LAUNDER(x) std::launder(x)
#else
#define TOML_LAUNDER(x) x
#endif

////////// FORWARD DECLARATIONS & TYPEDEFS

/// \brief The root namespace for all toml++ functions and types.
Expand Down
8 changes: 0 additions & 8 deletions include/toml++/toml_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ namespace toml
{
#if TOML_DOXYGEN || !TOML_EXCEPTIONS

#ifdef __cpp_lib_launder
#define TOML_LAUNDER(x) std::launder(x)
#else
#define TOML_LAUNDER(x) x
#endif

TOML_ABI_NAMESPACE_START(parse_noex)

/// \brief The result of a parsing operation.
Expand Down Expand Up @@ -264,8 +258,6 @@ namespace toml

TOML_ABI_NAMESPACE_END

#undef TOML_LAUNDER

#else

using parse_result = table;
Expand Down
78 changes: 62 additions & 16 deletions include/toml++/toml_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,68 +17,107 @@ namespace toml::impl
{
using value_type = std::conditional_t<IsConst, const node, node>;

const string& key;
value_type& value;
const string& first;
value_type& second;
};

template <bool IsConst>
class table_iterator final
{
private:
friend class toml::table;

using raw_iterator = std::conditional_t<
IsConst,
string_map<std::unique_ptr<node>>::const_iterator,
string_map<std::unique_ptr<node>>::iterator
>;

friend class ::toml::table;

using proxy_type = table_proxy_pair<IsConst>;
using raw_mutable_iterator = string_map<std::unique_ptr<node>>::iterator;
using raw_const_iterator = string_map<std::unique_ptr<node>>::const_iterator;
using raw_iterator = std::conditional_t<IsConst, raw_const_iterator, raw_mutable_iterator>;

mutable raw_iterator raw_;
mutable std::aligned_storage_t<sizeof(proxy_type), alignof(proxy_type)> proxy;
mutable bool proxy_instantiated = false;

table_iterator(const raw_iterator& raw) noexcept
[[nodiscard]]
proxy_type* get_proxy() const noexcept
{
if (!proxy_instantiated)
{
auto p = new (&proxy) proxy_type{ raw_->first, *raw_->second.get() };
proxy_instantiated = true;
return p;
}
else
return TOML_LAUNDER(reinterpret_cast<proxy_type*>(&proxy));
}

table_iterator(raw_mutable_iterator raw) noexcept
: raw_{ raw }
{}

table_iterator(raw_iterator&& raw) noexcept
: raw_{ std::move(raw) }
template <bool C = IsConst, typename = std::enable_if_t<C>>
TOML_NODISCARD_CTOR
table_iterator(raw_const_iterator raw) noexcept
: raw_{ raw }
{}

public:

table_iterator() noexcept = default;

using reference = table_proxy_pair<IsConst>;
using difference_type = ptrdiff_t;
table_iterator(const table_iterator& other) noexcept
: raw_{ other.raw_ }
{}

table_iterator& operator = (const table_iterator& rhs) noexcept
{
raw_ = rhs.raw_;
proxy_instantiated = false;
return *this;
}

using value_type = table_proxy_pair<IsConst>;
using reference = value_type&;
using pointer = value_type*;

table_iterator& operator++() noexcept // ++pre
{
++raw_;
proxy_instantiated = false;
return *this;
}

table_iterator operator++(int) noexcept // post++
{
table_iterator out{ raw_ };
++raw_;
proxy_instantiated = false;
return out;
}

table_iterator& operator--() noexcept // --pre
{
--raw_;
proxy_instantiated = false;
return *this;
}

table_iterator operator--(int) noexcept // post--
{
table_iterator out{ raw_ };
--raw_;
proxy_instantiated = false;
return out;
}

[[nodiscard]]
reference operator* () const noexcept
{
return { raw_->first, *raw_->second.get() };
return *get_proxy();
}

[[nodiscard]]
pointer operator -> () const noexcept
{
return get_proxy();
}

[[nodiscard]]
Expand All @@ -92,6 +131,13 @@ namespace toml::impl
{
return lhs.raw_ != rhs.raw_;
}

template <bool C = IsConst, typename = std::enable_if_t<!C>>
[[nodiscard]]
operator table_iterator<true>() const noexcept
{
return table_iterator<true>{ raw_ };
}
};

struct table_init_pair final
Expand Down

0 comments on commit 289c95c

Please sign in to comment.