From 299fe1c78d5245ee24caf6c1c44ec8a3a6ab84e2 Mon Sep 17 00:00:00 2001 From: Jesse Hoogervorst Date: Thu, 4 Jan 2024 15:03:07 +0100 Subject: [PATCH] Implemented Schema and Subschema move constructor and assignment operators. Default implementations were not sufficient, since raw pointers are not actually moved correctly automatically, resulting in segmentation faults. --- include/valijson/schema.hpp | 43 ++++++++++++++++++++++++++++------ include/valijson/subschema.hpp | 36 ++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/include/valijson/schema.hpp b/include/valijson/schema.hpp index 1659efd..a3ac541 100644 --- a/include/valijson/schema.hpp +++ b/include/valijson/schema.hpp @@ -42,11 +42,37 @@ public: // Disable copy assignment Schema & operator=(const Schema &) = delete; - // Default move construction - Schema(Schema &&other) = default; + /** + * @brief Move construct a new Schema + * + * @param other Schema that is moved into the new Schema + */ + Schema(Schema &&other) + : Subschema(std::move(other)), + subschemaSet(std::move(other.subschemaSet)), + sharedEmptySubschema(other.sharedEmptySubschema) + { + // Makes other invalid by setting sharedEmptySubschema to nullptr + other.sharedEmptySubschema = nullptr; + } - // Disable copy assignment - Schema & operator=(Schema &&) = default; + /** + * @brief Move assign a Schema + * + * @param other Schema that is move assigned to this Schema + * @return Schema& + */ + Schema & operator=(Schema &&other) + { + // Calls the base class move assignment operator + Subschema::operator=(std::move(other)); + + // Swaps all Schema members + std::swap(subschemaSet, other.subschemaSet); + std::swap(sharedEmptySubschema, other.sharedEmptySubschema); + + return *this; + } /** * @brief Clean up and free all memory managed by the Schema @@ -56,9 +82,12 @@ public: */ ~Schema() override { - sharedEmptySubschema->~Subschema(); - m_freeFn(const_cast(sharedEmptySubschema)); - sharedEmptySubschema = nullptr; + if(sharedEmptySubschema != nullptr) + { + sharedEmptySubschema->~Subschema(); + m_freeFn(const_cast(sharedEmptySubschema)); + sharedEmptySubschema = nullptr; + } #if VALIJSON_USE_EXCEPTIONS try { diff --git a/include/valijson/subschema.hpp b/include/valijson/subschema.hpp index be71c44..e454a38 100644 --- a/include/valijson/subschema.hpp +++ b/include/valijson/subschema.hpp @@ -43,11 +43,39 @@ public: // Disable copy assignment Subschema & operator=(const Subschema &) = delete; - // Default move construction - Subschema(Subschema &&) = default; + /** + * @brief Move construct a new Subschema + * + * @param other Subschema that is moved into the new Subschema + */ + Subschema(Subschema &&other) + : m_allocFn(other.m_allocFn), + m_freeFn(other.m_freeFn), + m_alwaysInvalid(std::move(other.m_alwaysInvalid)), + m_constraints(std::move(other.m_constraints)), + m_description(std::move(other.m_description)), + m_id(std::move(other.m_id)), + m_title(std::move(other.m_title)) { } - // Default move assignment - Subschema & operator=(Subschema &&) = default; + /** + * @brief Move assign a Subschema + * + * @param other Subschema that is move assigned to this Subschema + * @return Subschema& + */ + Subschema & operator=(Subschema &&other) + { + // Swaps all members + std::swap(m_allocFn, other.m_allocFn); + std::swap(m_freeFn, other.m_freeFn); + std::swap(m_alwaysInvalid, other.m_alwaysInvalid); + std::swap(m_constraints, other.m_constraints); + std::swap(m_description, other.m_description); + std::swap(m_id, other.m_id); + std::swap(m_title, other.m_title); + + return *this; + } /** * @brief Construct a new Subschema object