Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 130 additions & 99 deletions proxy/hdrs/MIME.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,59 @@ struct MIMECooked {
***********************************************************************/

struct MIMEHdrImpl : public HdrHeapObjImpl {
/** Iterator over fields in the header.
* This iterator should be stable over field deletes, but not insertions.
*/
class iterator
{
using self_type = iterator; ///< Self reference types.

public:
iterator() = default;

// STL iterator compliance types.
using difference_type = void;
using value_type = MIMEField;
using pointer = value_type *;
using reference = value_type &;
using iterator_category = std::forward_iterator_tag;

pointer operator->();
reference operator*();

self_type &operator++();
self_type operator++(int);

bool operator==(self_type const &that);
bool operator!=(self_type const &that);

protected:
MIMEFieldBlockImpl *_block = nullptr; ///< Current block.
unsigned _slot = 0; ///< Slot in @a _block

/** Internal constructor.
*
* @param block Block containing current field.
* @param slot Index of current field.
*/
iterator(MIMEFieldBlockImpl *block, unsigned slot) : _block(block), _slot(slot) { this->step(); }

/** Move to a valid (live) slot.
*
* This enforces the invariant that the iterator is exactly one of
* 1. referencing a valid slot
* 2. equal to the @c end iterator
*
* Therefore if called when the iterator is in state (1) the iterator is unchanged.
*
* @return @a this
*/
self_type &step();

friend class MIMEHdr;
friend struct MIMEHdrImpl;
};

// HdrHeapObjImpl is 4 bytes, so this will result in 4 bytes padding
uint64_t m_presence_bits;
uint32_t m_slot_accelerators[4];
Expand All @@ -275,8 +328,83 @@ struct MIMEHdrImpl : public HdrHeapObjImpl {
// Cooked values
void recompute_cooked_stuff(MIMEField *changing_field_or_null = nullptr);
void recompute_accelerators_and_presence_bits();

// Utility
/// Iterator for first field.
iterator begin();
/// Iterator past last field.
iterator end();
};

inline auto
MIMEHdrImpl::begin() -> iterator
{
return iterator(&m_first_fblock, 0);
}

inline auto
MIMEHdrImpl::end() -> iterator
{
return {}; // default constructed iterator.
}

inline auto
MIMEHdrImpl::iterator::step() -> self_type &
{
while (_block) {
for (auto limit = _block->m_freetop; _slot < limit; ++_slot) {
if (_block->m_field_slots[_slot].is_live()) {
return *this;
}
}
_block = _block->m_next;
_slot = 0;
}
return *this;
}

inline auto
MIMEHdrImpl::iterator::operator*() -> reference
{
return _block->m_field_slots[_slot];
}

inline auto
MIMEHdrImpl::iterator::operator->() -> pointer
{
return &(_block->m_field_slots[_slot]);
}

inline bool
MIMEHdrImpl::iterator::operator==(const self_type &that)
{
return _block == that._block && _slot == that._slot;
}

inline bool
MIMEHdrImpl::iterator::operator!=(const self_type &that)
{
return _block != that._block || _slot != that._slot;
}

inline auto
MIMEHdrImpl::iterator::operator++() -> self_type &
{
if (_block) {
++_slot;
this->step();
}
return *this;
}

inline auto
MIMEHdrImpl::iterator::operator++(int) -> self_type
{
self_type zret{*this};
++*this;
return zret;
}

/***********************************************************************
* *
* Parser *
Expand Down Expand Up @@ -986,42 +1114,7 @@ struct MIMEFieldIter {
class MIMEHdr : public HdrHeapSDKHandle
{
public:
/** Iterator over fields in the header.
* This iterator should be stable over field deletes, but not insertions.
*/
class iterator
{
using self_type = iterator; ///< Self reference types.

public:
iterator() = default;

// STL iterator compliance types.
using difference_type = void;
using value_type = MIMEField;
using pointer = value_type *;
using reference = value_type &;
using iterator_category = std::forward_iterator_tag;

pointer operator->();
reference operator*();

self_type &operator++();
self_type operator++(int);

bool operator==(self_type const &that);
bool operator!=(self_type const &that);

protected:
MIMEFieldBlockImpl *_block = nullptr; ///< Current block.
unsigned _slot = 0; ///< Slot in @a _block

/// Internal method to move to a valid slot.
/// If the current location is valid, this is a no-op.
self_type &step();

friend class MIMEHdr;
};
using iterator = MIMEHdrImpl::iterator;

MIMEHdrImpl *m_mime = nullptr;

Expand Down Expand Up @@ -1273,10 +1366,7 @@ MIMEHdr::field_delete(MIMEField *field, bool delete_all_dups)
inline auto
MIMEHdr::begin() const -> iterator
{
iterator spot;
spot._block = &m_mime->m_first_fblock;
spot._slot = 0;
return spot.step();
return m_mime ? m_mime->begin() : iterator();
}

inline auto
Expand All @@ -1285,65 +1375,6 @@ MIMEHdr::end() const -> iterator
return {}; // default constructed iterator.
}

inline auto
MIMEHdr::iterator::step() -> self_type &
{
while (_block) {
auto limit = _block->m_freetop;
while (_slot < limit) {
if (_block->m_field_slots[_slot].is_live()) {
return *this;
}
++_slot;
}
_block = _block->m_next;
_slot = 0;
}
return *this;
}

inline auto
MIMEHdr::iterator::operator*() -> reference
{
return _block->m_field_slots[_slot];
}

inline auto
MIMEHdr::iterator::operator->() -> pointer
{
return &(_block->m_field_slots[_slot]);
}

inline bool
MIMEHdr::iterator::operator==(const self_type &that)
{
return _block == that._block && _slot == that._slot;
}

inline bool
MIMEHdr::iterator::operator!=(const self_type &that)
{
return _block != that._block || _slot != that._slot;
}

inline auto
MIMEHdr::iterator::operator++() -> self_type &
{
if (_block) {
++_slot;
this->step();
}
return *this;
}

inline auto
MIMEHdr::iterator::operator++(int) -> self_type
{
self_type zret{*this};
this->step();
return zret;
}

inline void
MIMEHdr::field_delete(const char *name, int name_length)
{
Expand Down