// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. #include "precomp.h" #include "AttrRowIterator.hpp" #include "AttrRow.hpp" AttrRowIterator AttrRowIterator::CreateEndIterator(const ATTR_ROW* const attrRow) noexcept { AttrRowIterator it{ attrRow }; it._setToEnd(); return it; } AttrRowIterator::AttrRowIterator(const ATTR_ROW* const attrRow) noexcept : _pAttrRow{ attrRow }, _run{ attrRow->_list.cbegin() }, _currentAttributeIndex{ 0 }, _exceeded{ false } { } AttrRowIterator::operator bool() const noexcept { return !_exceeded && _run < _pAttrRow->_list.cend(); } bool AttrRowIterator::operator==(const AttrRowIterator& it) const noexcept { return (_pAttrRow == it._pAttrRow && _run == it._run && _currentAttributeIndex == it._currentAttributeIndex && _exceeded == it._exceeded); } bool AttrRowIterator::operator!=(const AttrRowIterator& it) const noexcept { return !(*this == it); } AttrRowIterator& AttrRowIterator::operator+=(const ptrdiff_t& movement) { if (!_exceeded) { if (movement >= 0) { _increment(gsl::narrow(movement)); } else { _decrement(gsl::narrow(-movement)); } } return *this; } AttrRowIterator& AttrRowIterator::operator-=(const ptrdiff_t& movement) { return this->operator+=(-movement); } const TextAttribute* AttrRowIterator::operator->() const { THROW_HR_IF(E_BOUNDS, _exceeded); return &_run->GetAttributes(); } const TextAttribute& AttrRowIterator::operator*() const { THROW_HR_IF(E_BOUNDS, _exceeded); return _run->GetAttributes(); } // Routine Description: // - increments the index the iterator points to // Arguments: // - count - the amount to increment by void AttrRowIterator::_increment(size_t count) noexcept { while (count > 0) { const size_t runLength = _run->GetLength(); if (count + _currentAttributeIndex < runLength) { _currentAttributeIndex += count; return; } else { count -= runLength - _currentAttributeIndex; ++_run; _currentAttributeIndex = 0; } } } // Routine Description: // - decrements the index the iterator points to // Arguments: // - count - the amount to decrement by void AttrRowIterator::_decrement(size_t count) noexcept { while (count > 0) { // If there's still space within this color attribute to move left, do so. if (count <= _currentAttributeIndex) { _currentAttributeIndex -= count; return; } // If there's not space, move to the previous attribute run // We'll walk through above on the if branch to move left further (if necessary) else { // make sure we don't go out of bounds if (_run == _pAttrRow->_list.cbegin()) { _exceeded = true; return; } count -= _currentAttributeIndex + 1; --_run; _currentAttributeIndex = _run->GetLength() - 1; } } } // Routine Description: // - sets fields on the iterator to describe the end() state of the ATTR_ROW void AttrRowIterator::_setToEnd() noexcept { _run = _pAttrRow->_list.cend(); _currentAttributeIndex = 0; }