From 7dd49c6293172b494c78918507242cdb55d35137 Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Sun, 21 Jan 2024 12:31:30 +0100 Subject: WIP --- sax/inc/sax_attributes.hh | 146 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 sax/inc/sax_attributes.hh (limited to 'sax/inc/sax_attributes.hh') diff --git a/sax/inc/sax_attributes.hh b/sax/inc/sax_attributes.hh new file mode 100644 index 0000000..4ab1a44 --- /dev/null +++ b/sax/inc/sax_attributes.hh @@ -0,0 +1,146 @@ +#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 -- cgit v1.2.3-70-g09d2