diff --git a/cmkr.cmake b/cmkr.cmake index 2379ad3..cdeea6e 100644 --- a/cmkr.cmake +++ b/cmkr.cmake @@ -2,7 +2,7 @@ include_guard() # Change these defaults to point to your infrastructure if desired set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) -set(CMKR_TAG "v0.2.17" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) +set(CMKR_TAG "v0.2.26" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE) # To bootstrap/generate a cmkr project: cmake -P cmkr.cmake diff --git a/include/zasm/program/node.hpp b/include/zasm/program/node.hpp index ad91bd8..0f39acb 100644 --- a/include/zasm/program/node.hpp +++ b/include/zasm/program/node.hpp @@ -11,9 +11,17 @@ #include #include #include +#include namespace zasm { + enum class NodeFlags : std::uint32_t + { + None = 0, + Attached = 1U << 0, + }; + ZASM_ENABLE_ENUM_OPERATORS(NodeFlags); + /// /// A type to hold data such as Instruction, Label, Data etc. within a doubly /// linked list managed by the Program. The data is internally stored as a variant @@ -29,11 +37,11 @@ namespace zasm protected: Id _id{ Id::Invalid }; + NodeFlags _flags{}; Node* _prev{}; Node* _next{}; std::variant _data{}; - private: union { std::uint64_t userdataU64; @@ -253,6 +261,17 @@ namespace zasm return static_cast>(_id) > static_cast>(other._id); } + + /// + /// If the node is not attached to a program it will return false. By default + /// nodes are not attached to a program when created. A call like Program::insetBefore + /// or Program::insertAfter will attach the node to the program. + /// + /// True if attached, false otherwise + bool isAttached() const noexcept + { + return (_flags & NodeFlags::Attached) != NodeFlags::None; + } }; } // namespace zasm diff --git a/src/zasm/src/program/program.cpp b/src/zasm/src/program/program.cpp index 2989907..67db6e5 100644 --- a/src/zasm/src/program/program.cpp +++ b/src/zasm/src/program/program.cpp @@ -6,6 +6,7 @@ #include "zasm/program/observer.hpp" #include +#include #include #include @@ -114,11 +115,22 @@ namespace zasm return _state->tail; } + static void attachNode(detail::Node* node) noexcept + { + // Can not attach a node twice. + assert(node->isAttached() == false); + + // Mark attached. + node->setAttached(true); + } + template Node* prepend_(Node* n, detail::ProgramState& state) noexcept { auto* head = detail::toInternal(state.head); auto* node = detail::toInternal(n); + attachNode(node); + node->setNext(state.head); node->setPrev(nullptr); @@ -147,7 +159,9 @@ namespace zasm template Node* append_(Node* n, detail::ProgramState& state) noexcept { auto* tail = detail::toInternal(state.tail); + auto* node = detail::toInternal(n); + attachNode(node); node->setNext(nullptr); if (tail == nullptr) @@ -179,6 +193,7 @@ namespace zasm auto* pos = detail::toInternal(nodePos); if (pos == nullptr) { + assert(false); return nullptr; // Impossible placement. } if (pos == state.head) @@ -186,8 +201,11 @@ namespace zasm return prepend_(nodeToInsert, state); } + assert(pos->isAttached()); auto* pre = detail::toInternal(pos->getPrev()); + auto* node = detail::toInternal(nodeToInsert); + attachNode(node); node->setPrev(pre); node->setNext(pos); @@ -219,8 +237,12 @@ namespace zasm return append_(nodeToInsert, state); } + assert(pos->isAttached()); + auto* next = detail::toInternal(pos->getNext()); + auto* node = detail::toInternal(nodeToInsert); + attachNode(node); pos->setNext(node); @@ -247,18 +269,17 @@ namespace zasm template static Node* detach_(Node* nodeToDetach, detail::ProgramState& state) noexcept { auto* node = detail::toInternal(nodeToDetach); - auto* pre = detail::toInternal(node->getPrev()); - auto* post = detail::toInternal(node->getNext()); - - if (pre == nullptr && post == nullptr) + if (!node->isAttached()) { - if (state.head != node && state.tail != node) - { - // Not part of the list. - return nullptr; - } + // Can't detach a node twice. + return nullptr; } + node->setAttached(false); + + auto* pre = detail::toInternal(node->getPrev()); + auto* post = detail::toInternal(node->getNext()); + notifyObservers(&Observer::onNodeDetach, state.observer, nodeToDetach); if (pre != nullptr) diff --git a/src/zasm/src/program/program.node.hpp b/src/zasm/src/program/program.node.hpp index 5465f26..0047601 100644 --- a/src/zasm/src/program/program.node.hpp +++ b/src/zasm/src/program/program.node.hpp @@ -27,6 +27,14 @@ namespace zasm { _id = id; } + + void setAttached(bool attached) noexcept + { + if (attached) + _flags = _flags | NodeFlags::Attached; + else + _flags = _flags & ~NodeFlags::Attached; + } }; static_assert(sizeof(Node) == sizeof(::zasm::Node));