a8e4bedae3
## Summary of the Pull Request Introduces `til::rle`, a vector-like container which stores elements of type T in a run length encoded format. This allows efficient compaction of repeated elements within the vector. ## References * #8000 - Supports buffer rewrite work. A re-use of `til::rle` will be useful as a column counter as we pursue NxM storage and presentation. * #3075 - The new iterators allow skipping forward by multiple units, which wasn't possible under `TextBuffer-/OutputCellIterator`. Additionally it also allows a bulk insertions. * #8787 and #410 - High probability this should be `pmr`-ified like `bitmap` for things like `chafa` and `cacafire` which are changing the run length frequently. ## PR Checklist * [x] Closes #8741 * [x] I work here. * [x] Tests added. * [x] Tests passed. ## Validation Steps Performed * [x] Ran `cacafire` in `OpenConsole.exe` and it looked beautiful * [x] Ran new suite of `RunLengthEncodingTests.cpp` Co-authored-by: Michael Niksa <miniksa@microsoft.com>
135 lines
4.1 KiB
C++
135 lines
4.1 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "precomp.h"
|
|
#include "AttrRow.hpp"
|
|
|
|
// Routine Description:
|
|
// - constructor
|
|
// Arguments:
|
|
// - cchRowWidth - the length of the default text attribute
|
|
// - attr - the default text attribute
|
|
// Return Value:
|
|
// - constructed object
|
|
ATTR_ROW::ATTR_ROW(const uint16_t width, const TextAttribute attr) :
|
|
_data(width, attr) {}
|
|
|
|
// Routine Description:
|
|
// - Sets all properties of the ATTR_ROW to default values
|
|
// Arguments:
|
|
// - attr - The default text attributes to use on text in this row.
|
|
void ATTR_ROW::Reset(const TextAttribute attr)
|
|
{
|
|
_data.replace(0, _data.size(), attr);
|
|
}
|
|
|
|
// Routine Description:
|
|
// - Takes an existing row of attributes, and changes the length so that it fills the NewWidth.
|
|
// If the new size is bigger, then the last attr is extended to fill the NewWidth.
|
|
// If the new size is smaller, the runs are cut off to fit.
|
|
// Arguments:
|
|
// - oldWidth - The original width of the row.
|
|
// - newWidth - The new width of the row.
|
|
// Return Value:
|
|
// - <none>, throws exceptions on failures.
|
|
void ATTR_ROW::Resize(const uint16_t newWidth)
|
|
{
|
|
_data.resize_trailing_extent(newWidth);
|
|
}
|
|
|
|
// Routine Description:
|
|
// - returns a copy of the TextAttribute at the specified column
|
|
// Arguments:
|
|
// - column - the column to get the attribute for
|
|
// Return Value:
|
|
// - the text attribute at column
|
|
// Note:
|
|
// - will throw on error
|
|
TextAttribute ATTR_ROW::GetAttrByColumn(const uint16_t column) const
|
|
{
|
|
return _data.at(column);
|
|
}
|
|
|
|
// Routine Description:
|
|
// - Finds the hyperlink IDs present in this row and returns them
|
|
// Return value:
|
|
// - The hyperlink IDs present in this row
|
|
std::vector<uint16_t> ATTR_ROW::GetHyperlinks() const
|
|
{
|
|
std::vector<uint16_t> ids;
|
|
for (const auto& run : _data.runs())
|
|
{
|
|
if (run.value.IsHyperlink())
|
|
{
|
|
ids.emplace_back(run.value.GetHyperlinkId());
|
|
}
|
|
}
|
|
return ids;
|
|
}
|
|
|
|
// Routine Description:
|
|
// - Sets the attributes (colors) of all character positions from the given position through the end of the row.
|
|
// Arguments:
|
|
// - iStart - Starting index position within the row
|
|
// - attr - Attribute (color) to fill remaining characters with
|
|
// Return Value:
|
|
// - <none>
|
|
bool ATTR_ROW::SetAttrToEnd(const uint16_t beginIndex, const TextAttribute attr)
|
|
{
|
|
_data.replace(gsl::narrow<uint16_t>(beginIndex), _data.size(), attr);
|
|
return true;
|
|
}
|
|
|
|
// Method Description:
|
|
// - Replaces all runs in the row with the given toBeReplacedAttr with the new
|
|
// attribute replaceWith.
|
|
// Arguments:
|
|
// - toBeReplacedAttr - the attribute to replace in this row.
|
|
// - replaceWith - the new value for the matching runs' attributes.
|
|
// Return Value:
|
|
// - <none>
|
|
void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith)
|
|
{
|
|
_data.replace_values(toBeReplacedAttr, replaceWith);
|
|
}
|
|
|
|
// Routine Description:
|
|
// - Takes an attribute, and merges it into this row from beginIndex (inclusive) to endIndex (exclusive).
|
|
// - For example, if the current row was was [{4, BLUE}], the merge arguments were
|
|
// { beginIndex = 1, endIndex = 3, newAttr = RED }, then the row would modified to be
|
|
// [{ 1, BLUE}, {2, RED}, {1, BLUE}].
|
|
// Arguments:
|
|
// - beginIndex, endIndex: The [beginIndex, endIndex) range that's to be replaced with newAttr.
|
|
// - newAttr: The attribute to merge into this row.
|
|
// Return Value:
|
|
// - <none>
|
|
void ATTR_ROW::Replace(const uint16_t beginIndex, const uint16_t endIndex, const TextAttribute& newAttr)
|
|
{
|
|
_data.replace(beginIndex, endIndex, newAttr);
|
|
}
|
|
|
|
ATTR_ROW::const_iterator ATTR_ROW::begin() const noexcept
|
|
{
|
|
return _data.begin();
|
|
}
|
|
|
|
ATTR_ROW::const_iterator ATTR_ROW::end() const noexcept
|
|
{
|
|
return _data.end();
|
|
}
|
|
|
|
ATTR_ROW::const_iterator ATTR_ROW::cbegin() const noexcept
|
|
{
|
|
return _data.cbegin();
|
|
}
|
|
|
|
ATTR_ROW::const_iterator ATTR_ROW::cend() const noexcept
|
|
{
|
|
return _data.cend();
|
|
}
|
|
|
|
bool operator==(const ATTR_ROW& a, const ATTR_ROW& b) noexcept
|
|
{
|
|
return a._data == b._data;
|
|
}
|