From e92e98805c1bc2389c21739e997bae1585e2a119 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Mon, 3 Jul 2023 08:30:02 -0700 Subject: [PATCH] feat: Array::emplace_back --- include/mrdox/Support/Dom.hpp | 52 ++++++++++++++++++++++ source/Support/Dom.cpp | 84 ++++++++++++++++++++++------------- 2 files changed, 105 insertions(+), 31 deletions(-) diff --git a/include/mrdox/Support/Dom.hpp b/include/mrdox/Support/Dom.hpp index d35c7efc1..bbd15cac7 100644 --- a/include/mrdox/Support/Dom.hpp +++ b/include/mrdox/Support/Dom.hpp @@ -124,6 +124,13 @@ class MRDOX_DECL */ value_type at(size_type i) const; + /** Append an element to the end of the array. + + If the array is read-only, an exception + is thrown. + */ + void emplace_back(value_type value); + /** Return a diagnostic string. */ friend @@ -162,6 +169,46 @@ class MRDOX_DECL /** Return the i-th element, without bounds checking. */ virtual value_type get(size_type i) const = 0; + + /** Append an element to the end of the array. + + The default implementation throws an exception, + making the array effectively read-only. + */ + virtual void emplace_back(value_type value); +}; + +//------------------------------------------------ +// +// DefaultArrayImpl +// +//------------------------------------------------ + +/** The default array implementation. + + This implementation is backed by a simple + vector and allows appending. +*/ +class MRDOX_DECL + DefaultArrayImpl : public ArrayImpl +{ +public: + /// @copydoc Array::value_type + using value_type = Array::value_type; + + /// @copydoc Array::size_type + using size_type = Array::size_type; + + /** The type of storage used by the default implementation. + */ + using storage_type = std::vector; + + size_type size() const override; + value_type get(size_type i) const override; + void emplace_back(value_type value) override; + +private: + std::vector elements_; }; /** Return a new array using a custom implementation. @@ -923,6 +970,11 @@ inline auto Array::at(std::size_t i) const -> value_type Error("out of range").Throw(); } +inline void Array::emplace_back(value_type value) +{ + impl_->emplace_back(std::move(value)); +} + //------------------------------------------------ inline bool Object::empty() const diff --git a/source/Support/Dom.cpp b/source/Support/Dom.cpp index 9ab859ad9..0018fb5d8 100644 --- a/source/Support/Dom.cpp +++ b/source/Support/Dom.cpp @@ -27,34 +27,6 @@ static_assert(std::ranges::random_access_range); // //------------------------------------------------ -namespace { - -class DefaultArrayImpl : public ArrayImpl -{ - std::vector v_; - -public: - std::size_t - size() const noexcept override - { - return v_.size(); - } - - Value get(std::size_t i) const override - { - MRDOX_ASSERT(i < v_.size()); - return v_[i]; - } -}; - -} // (anon) - -//------------------------------------------------ -// -// Array -// -//------------------------------------------------ - Array:: ~Array() = default; @@ -97,19 +69,60 @@ toString( return s; } +//------------------------------------------------ +// +// ArrayImpl +// //------------------------------------------------ ArrayImpl:: ~ArrayImpl() = default; +void +ArrayImpl:: +emplace_back( + value_type value) +{ + Error("Array is const").Throw(); +} + //------------------------------------------------ // -// Object +// DefaultArrayImpl // //------------------------------------------------ -ObjectImpl:: -~ObjectImpl() = default; +auto +DefaultArrayImpl:: +size() const -> + size_type +{ + return elements_.size(); +} + +auto +DefaultArrayImpl:: +get( + size_type i) const -> + value_type +{ + MRDOX_ASSERT(i < elements_.size()); + return elements_[i]; +} + +void +DefaultArrayImpl:: +emplace_back( + value_type value) +{ + elements_.emplace_back(std::move(value)); +} + +//------------------------------------------------ +// +// Object +// +//------------------------------------------------ Object:: ~Object() = default; @@ -169,6 +182,15 @@ toString( return s; } +//------------------------------------------------ +// +// ObjectImpl +// +//------------------------------------------------ + +ObjectImpl:: +~ObjectImpl() = default; + //------------------------------------------------ // // DefaultObjectImpl