#ifndef SAX_ATTRIBUTES_HH #define SAX_ATTRIBUTES_HH #include #include #include namespace modxml { namespace sax { struct Attribute { std::string_view name; std::string_view value; Attribute(std::string_view name, std::string_view value); }; /** * A view of attributes, with utility functions. */ class Attributes { public: virtual ~Attributes() = default; class iterator { public: using iterator_category = std::random_access_iterator_tag; using difference_type = std::ptrdiff_t; using element_type = Attribute; using pointer = element_type const *; using reference = element_type const &; iterator() : attributes_(nullptr), index_(0) {} iterator(iterator const& it) : attributes_(it.attributes_), index_(it.index_) {} iterator& operator=(iterator const& it) { attributes_ = it.attributes_; index_ = it.index_; return *this; } /** * Comparing two iterators from different Attributes instances is undefined. */ bool operator==(iterator const& it) const { return index_ == it.index_; } std::strong_ordering operator<=>(iterator const& it) const { return index_ <=> it.index_; } pointer operator->() const { return &attributes_->at(index_); } reference operator*() const { return attributes_->at(index_); } reference operator[](difference_type i) const { return attributes_->at(index_ + i); } iterator& operator++() { ++index_; return *this; } iterator operator++(int) { auto ret = *this; ++index_; return ret; } iterator& operator+=(difference_type i) { index_ += i; return *this; } iterator operator+(difference_type i) const { return iterator(attributes_, index_ + i); } friend iterator operator+(difference_type i, iterator const &it) { return iterator(it.attributes_, it.index_ + i); } iterator& operator--() { --index_; return *this; } iterator operator--(int) { auto ret = *this; --index_; return ret; } iterator& operator-=(difference_type i) { index_ -= i; return *this; } difference_type operator-(iterator const& it) const { return index_ - it.index_; } iterator operator-(difference_type i) const { return iterator(attributes_, index_ - i); } protected: iterator(Attributes const* attributes, std::size_t index) : attributes_(attributes), index_(index) {} private: Attributes const* attributes_; std::size_t index_; }; static_assert(std::random_access_iterator); virtual iterator begin() const = 0; virtual iterator end() const = 0; virtual std::size_t size() const = 0; /** * name and value of attribute are valid as long as Attributes instance is. */ virtual Attribute const& at(std::size_t index) const = 0; Attribute const& operator[](std::size_t index) const { return at(index); } /** * Return the first attribute with name, if any. */ virtual std::optional find_first( std::string_view name) const; /** * Return the last attribute with name, if any. */ virtual std::optional find_last( std::string_view name) const; /** * Return the index of the attribute with name, starting with offset. */ virtual std::optional find(std::string_view name, std::size_t index = 0) const; protected: Attributes() = default; }; } // namespace sax } // namespace modxml #endif // SAX_ATTRIBUTES_HH