diff --git a/include/matador/object/schema.hpp b/include/matador/object/schema.hpp index 5b87edc..8fef66c 100644 --- a/include/matador/object/schema.hpp +++ b/include/matador/object/schema.hpp @@ -3,6 +3,7 @@ #include "matador/object/error_code.hpp" #include "matador/object/schema_node.hpp" +#include "matador/object/schema_node_iterator.hpp" #include "matador/utils/result.hpp" #include "matador/utils/error.hpp" @@ -15,6 +16,8 @@ namespace matador::object { class schema { public: + typedef const_schema_node_iterator const_iterator; /**< Shortcut for the list const iterator. */ + schema(); template @@ -36,6 +39,20 @@ public: return utils::ok(); } + /** + * Return the first schema node. + * + * @return The first schema node iterator. + */ + [[nodiscard]] const_iterator begin() const; + + /** + * Return the last schema node. + * + * @return The last schema node iterator. + */ + [[nodiscard]] const_iterator end() const; + [[nodiscard]] bool empty() const; [[nodiscard]] size_t size() const; diff --git a/include/matador/object/schema_node.hpp b/include/matador/object/schema_node.hpp index 0ba6722..30d9421 100644 --- a/include/matador/object/schema_node.hpp +++ b/include/matador/object/schema_node.hpp @@ -56,7 +56,8 @@ private: private: - friend schema; + friend class schema; + friend class const_schema_node_iterator; schema &schema_; std::unique_ptr info_; diff --git a/include/matador/object/schema_node_iterator.hpp b/include/matador/object/schema_node_iterator.hpp new file mode 100644 index 0000000..60503e3 --- /dev/null +++ b/include/matador/object/schema_node_iterator.hpp @@ -0,0 +1,130 @@ +#ifndef SCHEMA_NODE_ITERATOR_HPP +#define SCHEMA_NODE_ITERATOR_HPP + +#include "matador/object/schema_node.hpp" + +#include + +namespace matador::object { + +class const_schema_node_iterator { +public: + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = schema_node; + using pointer = value_type*; + using reference = value_type&; + + /** + * Creates an empty iterator + */ + const_schema_node_iterator() = default; + + /** + * @brief Creates an iterator for a concrete type. + * + * This constructor creates an iterator for a concrete + * type and a concrete object. + * + * @param node The schema node of the object + */ + explicit const_schema_node_iterator(std::shared_ptr node); + + /** + * Copy from a given const_object_view_iterator. + * + * @param x The prototype_iterator to copy from. + */ + const_schema_node_iterator(const const_schema_node_iterator &x) = default; + + /** + * Assign from a given prototype_iterator. + * + * @param x The prototype_iterator to assign from. + * @return The assigned prototype_iterator. + */ + const_schema_node_iterator& operator=(const const_schema_node_iterator &x) = default; + + ~const_schema_node_iterator() = default; + + /** + * @brief Compares this with another iterators. + * + * Compares this with another iterators. Returns true + * if the iterators node prototype_type are the same. + * + * @param i The iterator to compare with. + * @return True if the iterators are the same. + */ + bool operator==(const const_schema_node_iterator &i) const; + + /** + * @brief Compares this with another iterators. + * + * Compares this with another iterators. Returns true + * if the iterators node prototype_node are not the same. + * + * @param i The iterator to compare with. + * @return True if the iterators are not the same. + */ + bool operator!=(const const_schema_node_iterator &i) const; + + /** + * Pre increments the iterator + * + * @return Returns iterators successor. + */ + const_schema_node_iterator& operator++(); + + /** + * Post increments the iterator + * + * @return Returns iterator before incrementing. + */ + const_schema_node_iterator operator++(int); + + /** + * Pre increments the iterator + * + * @return Returns iterators predecessor. + */ + const_schema_node_iterator& operator--(); + + /** + * Post decrements the iterator + * + * @return Returns iterator before decrementing. + */ + const_schema_node_iterator operator--(int); + + /** + * Returns the pointer to the node. + * + * @return The pointer to the node. + */ + pointer operator->() const; + + /** + * Returns the node. + * + * @return The iterators underlying node. + */ + const reference operator*() const; + + /** + * Returns the pointer to the node. + * + * @return The pointer to the node. + */ + [[nodiscard]] pointer get() const; + +private: + void increment(); + void decrement(); + +private: + std::shared_ptr node_; +}; + +} +#endif //SCHEMA_NODE_ITERATOR_HPP diff --git a/source/core/CMakeLists.txt b/source/core/CMakeLists.txt index 1e05046..c5076fb 100644 --- a/source/core/CMakeLists.txt +++ b/source/core/CMakeLists.txt @@ -47,6 +47,8 @@ add_library(matador-core STATIC object/schema.cpp object/schema_node.cpp object/basic_object_info.cpp + ../../include/matador/object/schema_node_iterator.hpp + object/schema_node_iterator.cpp ) target_link_libraries(matador-core ${CMAKE_DL_LIBS}) diff --git a/source/core/object/schema.cpp b/source/core/object/schema.cpp index bb41ac5..4033efb 100644 --- a/source/core/object/schema.cpp +++ b/source/core/object/schema.cpp @@ -14,11 +14,21 @@ schema::schema() root_->last_child_->previous_sibling_ = root_->first_child_; } +schema::const_iterator schema::begin() const { + return const_iterator(root_->first_child_->next_sibling_); +} + +schema::const_iterator schema::end() const { + return const_iterator(root_->last_child_); +} + bool schema::empty() const { return root_->first_child_ == root_->last_child_->previous_sibling_; } -size_t schema::size() const { return 0; } +size_t schema::size() const { + return static_cast(std::distance(begin(), end())); +} utils::result, utils::error> schema::attach_node(const std::shared_ptr &node, const std::string &parent) { diff --git a/source/core/object/schema_node_iterator.cpp b/source/core/object/schema_node_iterator.cpp new file mode 100644 index 0000000..1a65373 --- /dev/null +++ b/source/core/object/schema_node_iterator.cpp @@ -0,0 +1,106 @@ +#include + +#include "matador/object/schema_node_iterator.hpp" + +namespace matador::object { + +const_schema_node_iterator::const_schema_node_iterator(std::shared_ptr node) +: node_(std::move(node)) +{} + +bool const_schema_node_iterator::operator==(const const_schema_node_iterator &i) const +{ + return (node_ == i.node_); +} + +bool const_schema_node_iterator::operator!=(const const_schema_node_iterator &i) const +{ + return !operator==(i); +} + +const_schema_node_iterator& const_schema_node_iterator::operator++() +{ + increment(); + return *this; +} + +const_schema_node_iterator const_schema_node_iterator::operator++(int) +{ + const std::shared_ptr tmp = node_; + increment(); + return const_schema_node_iterator(tmp); +} + +const_schema_node_iterator& const_schema_node_iterator::operator--() +{ + decrement(); + return *this; +} + +const_schema_node_iterator const_schema_node_iterator::operator--(int) +{ + const std::shared_ptr tmp = node_; + decrement(); + return const_schema_node_iterator(tmp); +} + +const_schema_node_iterator::pointer const_schema_node_iterator::operator->() const +{ + return node_.get(); +} + +const_schema_node_iterator::reference const_schema_node_iterator::operator*() const +{ + return *node_; +} + +const_schema_node_iterator::pointer const_schema_node_iterator::get() const +{ + return node_.get(); +} + +void const_schema_node_iterator::increment() +{ + if (!node_) { + return; + } + + // if we have a child, child is the next iterator to return + // (if we don't do iterate over the siblings) + if (node_->first_child_ && node_->first_child_->next_sibling_ != node_->last_child_) { + node_ = node_->first_child_->next_sibling_; + } else { + // if there is no child, we check for sibling + // if there is a sibling, this is our next iterator to return + // if not, we go back to the parent + std::shared_ptr node = node_; + while (node_->parent_ && node_->next_sibling_ == node_->parent_->last_child_) { + node = node->parent_; + } + node_ = node_->next_sibling_; + } + +} +void const_schema_node_iterator::decrement() +{ + if (!node_) { + return; + } + // if node has a previous sibling, we set it + // as our next iterator. then we check if there + // are last children. if so, we set the last-last + // child as our iterator + if (node_->previous_sibling_ && node_->previous_sibling_->previous_sibling_) { + std::shared_ptr node = node_->previous_sibling_; + while (node_->last_child_ && node_->first_child_->next_sibling_ != node_->last_child_) { + node = node->last_child_->previous_sibling_; + } + node_ = node; + // if there is no previous sibling, our next iterator + // is the parent of the node + } else { + node_ = node_->parent_; + } +} + +} \ No newline at end of file