/*
* The motivation for another string is to have utf8 valid string replacing
* all bad things with FFFFD replacement character and filtering \0 and other
- * strange stuff defined by policies
+ * strange stuff defined by policies.
* This string always exclude \0 characters and ignore them! This is how MUA acts,
- * and we also store a flag about bad characters
+ * and we also store a flag about bad characters.
+ * Mime string iterators are always const, so the underlying storage should not
+ * be modified externally.
*/
-template<class T=char, class Allocator = std::allocator<T>> class basic_mime_string;
+template<class T=char, class Allocator = std::allocator<T>,
+ class Functor = fu2::function_view<UChar32(UChar32)>> class basic_mime_string;
using mime_string = basic_mime_string<char>;
template<typename Container, bool Raw = false>
struct iterator_base
{
- template<typename, typename>
+ template<typename, typename, typename>
friend class basic_mime_string;
public:
iterator_base& operator=( const iterator_base& ) noexcept = default;
Container* get_instance() const noexcept { return cont_instance; }
- value_type get_value() const noexcept { return cont_instance->storage.at(idx, std::nothrow); }
+ value_type get_value() const noexcept { return cont_instance->get_storage().at(idx); }
protected:
difference_type idx;
Container* cont_instance = nullptr;
}
};
-template<typename Container, bool Raw>
-struct const_iterator : iterator<Container, Raw> {
- const_iterator(typename iterator_base<Container, Raw>::difference_type index, const Container *instance) noexcept:
- iterator<Container, Raw>(index, const_cast<Container *>(instance))
- {
- }
-
- const_iterator(const iterator<Container, Raw> &other) noexcept:
- iterator<Container, Raw>(other)
- {
- }
-
- const_iterator() noexcept = default;
-
- const_iterator(const const_iterator &) noexcept = default;
-
- const_iterator &operator=(const const_iterator &) noexcept = default;
-
- const typename iterator<Container, Raw>::reference_type operator*() const noexcept
- {
- return this->get_value();
- }
-};
-
-template<class T, class Allocator>
+template<class T, class Allocator, class Functor>
class basic_mime_string : private Allocator {
public:
using storage_type = std::basic_string<T, std::char_traits<T>, Allocator>;
using view_type = std::basic_string_view<T, std::char_traits<T>>;
- using filter_type = fu2::function_view<UChar32 (UChar32)>;
+ using filter_type = Functor;
using codepoint_type = UChar32;
using value_type = T;
using difference_type = std::ptrdiff_t;
using iterator = rspamd::mime::iterator<basic_mime_string, false>;
- using const_iterator = rspamd::mime::const_iterator<basic_mime_string, false>;
using raw_iterator = rspamd::mime::iterator<basic_mime_string, true>;
- using raw_const_iterator = rspamd::mime::const_iterator<basic_mime_string, true>;
/* Ctors */
basic_mime_string() noexcept : Allocator() {}
explicit basic_mime_string(const Allocator& alloc) noexcept : Allocator(alloc) {}
return false;
}
- inline iterator begin() noexcept
- {
- return {0, this};
- }
-
- inline const_iterator begin() const noexcept
- {
- return {0, this};
- }
-
- inline raw_iterator raw_begin() noexcept
+ inline auto begin() noexcept -> iterator
{
return {0, this};
}
- inline raw_const_iterator raw_begin() const noexcept
+ inline auto raw_begin() noexcept -> raw_iterator
{
return {0, this};
}
- inline iterator end() noexcept
+ inline auto end() noexcept -> iterator
{
return {(difference_type) size(), this};
}
- inline const_iterator end() const noexcept
+ inline auto raw_end() noexcept -> raw_iterator
{
return {(difference_type) size(), this};
}
- inline raw_iterator raw_end() noexcept
+ inline auto get_storage() const noexcept -> const storage_type &
{
- return {(difference_type) size(), this};
- }
-
- inline raw_const_iterator raw_end() const noexcept
- {
- return {(difference_type) size(), this};
+ return storage;
}
/* For doctest stringify */