It compiles!
This commit is contained in:
parent
8114fa0dd0
commit
33e9a9b22a
|
@ -9,39 +9,6 @@ class RunLengthEncodingTests;
|
|||
|
||||
namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
template<typename T, typename S = size_t>
|
||||
class _rle_run
|
||||
{
|
||||
public:
|
||||
_rle_run(const S length, const T value) :
|
||||
_length(length),
|
||||
_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
S _length;
|
||||
T _value;
|
||||
|
||||
std::wstring to_string() const
|
||||
{
|
||||
return wil::str_printf<std::wstring>(L"[%td for %td]", _value, _length);
|
||||
}
|
||||
|
||||
constexpr bool operator==(const _rle_run& other) const noexcept
|
||||
{
|
||||
return _length == other._length &&
|
||||
_value == other._value;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const _rle_run& other) const noexcept
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T, typename S = size_t>
|
||||
class rle
|
||||
{
|
||||
|
@ -69,7 +36,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
T at(S position, S& applies)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, position >= _size);
|
||||
return _find(position, applies)->_value;
|
||||
return _find(position, applies)->first;
|
||||
}
|
||||
|
||||
// Replaces every value seen in the run with a new one
|
||||
|
@ -78,9 +45,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
{
|
||||
for (auto& run : _list)
|
||||
{
|
||||
if (run._value == oldValue)
|
||||
if (run.first == oldValue)
|
||||
{
|
||||
run._value = newValue;
|
||||
run.first = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +67,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
auto& run = _list.at(runPos);
|
||||
|
||||
// Extend its length by the additional columns we're adding.
|
||||
run.SetLength(run.GetLength() + newSize - _size);
|
||||
run.second = run.second + newSize - _size;
|
||||
|
||||
// Store that the new total width we represent is the new width.
|
||||
_size = newSize;
|
||||
|
@ -118,7 +85,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// then when we called FindAttrIndex, it returned the B5 as the pIndexedRun and a 2 for how many more segments it covers
|
||||
// after and including the 3rd column.
|
||||
// B5-2 = B3, which is what we desire to cover the new 3 size buffer.
|
||||
run._length = run._length - CountOfAttr + 1;
|
||||
run.second = run.second - CountOfAttr + 1;
|
||||
|
||||
// Store that the new total width we represent is the new width.
|
||||
_size = newSize;
|
||||
|
@ -136,21 +103,21 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// If no start is specified, fills the entire list.
|
||||
void fill(const T value, const S start = gsl::narrow_cast<S>(0))
|
||||
{
|
||||
_list.assign(1, til::details::_rle_run<T, S>{ gsl::narrow<S>(_size - start), value });
|
||||
_list.assign(1, std::pair<T, S>{ value, gsl::narrow<S>(_size - start) });
|
||||
}
|
||||
|
||||
// Inserts this value at the given position for the given run length.
|
||||
void insert(const T value, const S position, const S length = gsl::narrow_cast<S>(1))
|
||||
{
|
||||
til::details::_rle_run<T, S> item{ length, value };
|
||||
std::pair<T, S> item{ value, length };
|
||||
|
||||
_merge(gsl::span<til::details::_rle_run<T, S>>{ &item, gsl::narrow_cast<S>(1) }, position);
|
||||
_merge(gsl::span<std::pair<T, S>>{ &item, gsl::narrow_cast<S>(1) }, position);
|
||||
}
|
||||
|
||||
constexpr bool operator==(const rle& other) const noexcept
|
||||
{
|
||||
return _size == other._size &&
|
||||
std::equal(_list.cbegin(), _list.cend(), other.cbegin());
|
||||
std::equal(_list.cbegin(), _list.cend(), other._list.cbegin());
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const rle& other) const noexcept
|
||||
|
@ -166,7 +133,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
|
||||
for (auto& item : _list)
|
||||
{
|
||||
wss << item.to_string() << L" ";
|
||||
wss << wil::str_printf<std::wstring>(L"[%td for %td]", item.first, item.second) << L" ";
|
||||
}
|
||||
|
||||
wss << std::endl;
|
||||
|
@ -187,7 +154,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
auto runPos = _list.cbegin();
|
||||
do
|
||||
{
|
||||
totalLength += runPos->_length;
|
||||
totalLength += runPos->second;
|
||||
|
||||
if (totalLength > position)
|
||||
{
|
||||
|
@ -216,7 +183,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
return runPos;
|
||||
}
|
||||
|
||||
void _merge(const gsl::span<const til::details::_rle_run<T, S>> newItems,
|
||||
void _merge(const gsl::span<std::pair<T, S>> newItems,
|
||||
const S startIndex)
|
||||
{
|
||||
// Definitions:
|
||||
|
@ -236,8 +203,8 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// Do the -1 math here now so we don't have to have -1s scattered all over this function.
|
||||
const size_t iLastBufferCol = _size - 1;
|
||||
|
||||
const S endIndex = std::accumulate(newItems.begin(), newItems.end(), 0, [](S sum, til::details::_rle_run<T, S> item) {
|
||||
return sum + item->_length;
|
||||
const S endIndex = std::accumulate(newItems.begin(), newItems.end(), gsl::narrow_cast<S>(0), [](S sum, std::pair<T, S> item) {
|
||||
return sum + item.second;
|
||||
});
|
||||
|
||||
// If the insertion size is 1, do some pre-processing to
|
||||
|
@ -245,11 +212,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
if (newItems.size() == 1)
|
||||
{
|
||||
// Get the new color attribute we're trying to apply
|
||||
const T NewAttr = til::at(newItems, 0)._value;
|
||||
const T NewAttr = til::at(newItems, 0).first;
|
||||
|
||||
// If the existing run was only 1 element...
|
||||
// ...and the new color is the same as the old, we don't have to do anything and can exit quick.
|
||||
if (_list.size() == 1 && _list.at(0)._value == NewAttr)
|
||||
if (_list.size() == 1 && _list.at(0).first == NewAttr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -265,7 +232,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
for (size_t i = 0; i < _list.size(); i++)
|
||||
{
|
||||
const auto curr = begin + i;
|
||||
upperBound += curr->GetLength();
|
||||
upperBound += curr->second;
|
||||
|
||||
if (startIndex >= lowerBound && startIndex < upperBound)
|
||||
{
|
||||
|
@ -277,7 +244,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
//
|
||||
// 'B' is the new color and '^' represents where startIndex is. We don't have to
|
||||
// do anything.
|
||||
if (curr->GetAttributes() == NewAttr)
|
||||
if (curr->first == NewAttr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -290,9 +257,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// AAAAADCCCCCCCCC
|
||||
//
|
||||
// Here 'D' is the new color.
|
||||
if (curr->GetLength() == 1)
|
||||
if (curr->second == 1)
|
||||
{
|
||||
curr->SetAttributes(NewAttr);
|
||||
curr->first = NewAttr;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -308,13 +275,13 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// AAAAAABBBBBBCCC
|
||||
//
|
||||
// Here 'A' is the new color.
|
||||
if (NewAttr == prev->GetAttributes())
|
||||
if (NewAttr == prev->first)
|
||||
{
|
||||
prev->IncrementLength();
|
||||
curr->DecrementLength();
|
||||
prev->second++;
|
||||
curr->second--;
|
||||
|
||||
// If we just reduced the right half to zero, just erase it out of the list.
|
||||
if (curr->GetLength() == 0)
|
||||
if (curr->second == 0)
|
||||
{
|
||||
_list.erase(curr);
|
||||
}
|
||||
|
@ -335,12 +302,12 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
//
|
||||
// Here 'B' is the new color.
|
||||
const auto next = std::next(curr, 1);
|
||||
if (NewAttr == next->GetAttributes())
|
||||
if (NewAttr == next->first)
|
||||
{
|
||||
curr->DecrementLength();
|
||||
next->IncrementLength();
|
||||
curr->second--;
|
||||
next->second++;
|
||||
|
||||
if (curr->GetLength() == 0)
|
||||
if (curr->second == 0)
|
||||
{
|
||||
_list.erase(curr);
|
||||
}
|
||||
|
@ -402,7 +369,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
while (iExistingRunCoverage < startIndex)
|
||||
{
|
||||
// Add up how much length we can cover by copying an item from the existing run.
|
||||
iExistingRunCoverage += pExistingRunPos->GetLength();
|
||||
iExistingRunCoverage += pExistingRunPos->second;
|
||||
|
||||
// Copy it to the new run buffer and advance both pointers.
|
||||
newRun.push_back(*pExistingRunPos++);
|
||||
|
@ -425,7 +392,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// the new/final run.
|
||||
|
||||
// Fetch out the length so we can fix it up based on the below conditions.
|
||||
size_t length = newRun.back().GetLength();
|
||||
size_t length = newRun.back().second;
|
||||
|
||||
// If we've covered more cells already than the start of the attributes to be inserted...
|
||||
if (iExistingRunCoverage > startIndex)
|
||||
|
@ -440,9 +407,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// Now we're still on that "last cell copied" into the new run.
|
||||
// If the color of that existing copied cell matches the color of the first segment
|
||||
// of the run we're about to insert, we can just increment the length to extend the coverage.
|
||||
if (newRun.back()._value == pInsertRunPos->GetAttributes())
|
||||
if (newRun.back().first == pInsertRunPos->first)
|
||||
{
|
||||
length += pInsertRunPos->GetLength();
|
||||
length += pInsertRunPos->second;
|
||||
|
||||
// Since the color matched, we have already "used up" part of the insert run
|
||||
// and can skip it in our big "memcopy" step below that will copy the bulk of the insert run.
|
||||
|
@ -451,7 +418,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
}
|
||||
|
||||
// We're done manipulating the length. Store it back.
|
||||
newRun.back().SetLength(length);
|
||||
newRun.back().second = length;
|
||||
}
|
||||
|
||||
// Bulk copy the majority (or all, depending on circumstance) of the insert run into the final run buffer.
|
||||
|
@ -465,7 +432,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
while (iExistingRunCoverage <= endIndex)
|
||||
{
|
||||
FAIL_FAST_IF(!(pExistingRunPos != pExistingRunEnd));
|
||||
iExistingRunCoverage += pExistingRunPos->GetLength();
|
||||
iExistingRunCoverage += pExistingRunPos->second;
|
||||
pExistingRunPos++;
|
||||
}
|
||||
|
||||
|
@ -495,11 +462,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// This case is slightly off from the example above. This case is for if the B2 above was actually Y2.
|
||||
// That Y2 from the existing run is the same color as the Y2 we just filled a few columns left in the final run
|
||||
// so we can just adjust the final run's column count instead of adding another segment here.
|
||||
if (newRun.back()._value == pExistingRunPos->GetAttributes())
|
||||
if (newRun.back().first == pExistingRunPos->first)
|
||||
{
|
||||
size_t length = newRun.back().GetLength();
|
||||
size_t length = newRun.back().second;
|
||||
length += (iExistingRunCoverage - (endIndex + 1));
|
||||
newRun.back().SetLength(length);
|
||||
newRun.back().second = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -510,11 +477,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
newRun.emplace_back();
|
||||
|
||||
// Copy the existing run's color information to the new run
|
||||
newRun.back().SetAttributes(pExistingRunPos->GetAttributes());
|
||||
newRun.back().first = pExistingRunPos->first;
|
||||
|
||||
// Adjust the length of that copied color to cover only the reduced number of columns needed
|
||||
// now that some have been replaced by the insert run.
|
||||
newRun.back().SetLength(iExistingRunCoverage - (endIndex + 1));
|
||||
newRun.back().second = iExistingRunCoverage - (endIndex + 1);
|
||||
}
|
||||
|
||||
// Now that we're done recovering a piece of the existing run we skipped, move the pointer forward again.
|
||||
|
@ -532,12 +499,12 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// New Run desired when done = R3 -> B7
|
||||
// Existing run pointer is on B2.
|
||||
// We want to merge the 2 from the B2 into the B5 so we get B7.
|
||||
else if (newRun.back()._value == pExistingRunPos->GetAttributes())
|
||||
else if (newRun.back().first == pExistingRunPos->first)
|
||||
{
|
||||
// Add the value from the existing run into the current new run position.
|
||||
size_t length = newRun.back().GetLength();
|
||||
length += pExistingRunPos->GetLength();
|
||||
newRun.back().SetLength(length);
|
||||
size_t length = newRun.back().second;
|
||||
length += pExistingRunPos->second;
|
||||
newRun.back().second = length;
|
||||
|
||||
// Advance the existing run position since we consumed its value and merged it in.
|
||||
pExistingRunPos++;
|
||||
|
@ -555,9 +522,8 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
return;
|
||||
}
|
||||
|
||||
boost::container::small_vector<til::details::_rle_run<T>, 1> _list;
|
||||
boost::container::small_vector<std::pair<T, S>, 1> _list;
|
||||
S _size;
|
||||
T _defaultValue;
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class ::RunLengthEncodingTests;
|
||||
|
|
|
@ -31,7 +31,7 @@ class RunLengthEncodingTests
|
|||
|
||||
TEST_METHOD(AtPos)
|
||||
{
|
||||
til::rle<UINT> rle(10, 10);
|
||||
til::rle<int> rle(10, 10);
|
||||
rle.insert(3, 0, 4);
|
||||
rle.insert(7, 4, 2);
|
||||
rle.insert(11, 6, 3);
|
||||
|
@ -51,7 +51,7 @@ class RunLengthEncodingTests
|
|||
|
||||
TEST_METHOD(AtPosApplies)
|
||||
{
|
||||
til::rle<UINT> rle(10, 10);
|
||||
til::rle<int> rle(10, 10);
|
||||
rle.insert(3, 0, 4);
|
||||
rle.insert(7, 4, 2);
|
||||
rle.insert(11, 6, 3);
|
||||
|
@ -92,7 +92,7 @@ class RunLengthEncodingTests
|
|||
|
||||
TEST_METHOD(Replace)
|
||||
{
|
||||
til::rle<UINT> actual(20, 10);
|
||||
til::rle<int> actual(20, 10);
|
||||
actual.insert(3, 0, 4);
|
||||
actual.insert(7, 4, 2);
|
||||
actual.insert(11, 6, 3);
|
||||
|
@ -105,7 +105,7 @@ class RunLengthEncodingTests
|
|||
actual.replace(9, 81);
|
||||
actual.replace(3, 9);
|
||||
|
||||
til::rle<UINT> expected(20, 10);
|
||||
til::rle<int> expected(20, 10);
|
||||
expected.insert(9, 0, 4);
|
||||
expected.insert(49, 4, 2);
|
||||
expected.insert(11, 6, 3);
|
||||
|
@ -117,7 +117,7 @@ class RunLengthEncodingTests
|
|||
|
||||
TEST_METHOD(ResizeShrink)
|
||||
{
|
||||
til::rle<UINT> actual(10, 10);
|
||||
til::rle<int> actual(10, 10);
|
||||
actual.insert(3, 0, 4);
|
||||
actual.insert(7, 4, 2);
|
||||
actual.insert(11, 6, 3);
|
||||
|
@ -126,7 +126,7 @@ class RunLengthEncodingTests
|
|||
// 3 3 3 3 7 7 11 11 11 4
|
||||
// 3 for 4, 7 for 2, 11 for 3, 4 for 1.
|
||||
|
||||
til::rle<UINT> expected(7, 10);
|
||||
til::rle<int> expected(7, 10);
|
||||
actual.insert(3, 0, 4);
|
||||
actual.insert(7, 4, 2);
|
||||
actual.insert(11, 6, 1);
|
||||
|
@ -139,7 +139,7 @@ class RunLengthEncodingTests
|
|||
|
||||
TEST_METHOD(ResizeGrow)
|
||||
{
|
||||
til::rle<UINT> actual(10, 10);
|
||||
til::rle<int> actual(10, 10);
|
||||
actual.insert(3, 0, 4);
|
||||
actual.insert(7, 4, 2);
|
||||
actual.insert(11, 6, 3);
|
||||
|
@ -148,7 +148,7 @@ class RunLengthEncodingTests
|
|||
// 3 3 3 3 7 7 11 11 11 4
|
||||
// 3 for 4, 7 for 2, 11 for 3, 4 for 1.
|
||||
|
||||
til::rle<UINT> expected(13, 10);
|
||||
til::rle<int> expected(13, 10);
|
||||
actual.insert(3, 0, 4);
|
||||
actual.insert(7, 4, 2);
|
||||
actual.insert(11, 6, 3);
|
||||
|
@ -162,28 +162,28 @@ class RunLengthEncodingTests
|
|||
|
||||
TEST_METHOD(FillAll)
|
||||
{
|
||||
til::rle<UINT> actual(10, 10);
|
||||
til::rle<int> actual(10, 10);
|
||||
actual.insert(3, 0, 4);
|
||||
actual.insert(7, 4, 2);
|
||||
actual.insert(11, 6, 3);
|
||||
actual.insert(4, 9, 1);
|
||||
actual.fill(20);
|
||||
|
||||
til::rle<UINT> expected(10, 20);
|
||||
til::rle<int> expected(10, 20);
|
||||
|
||||
VERIFY_ARE_EQUAL(expected, actual);
|
||||
}
|
||||
|
||||
TEST_METHOD(FillFrom)
|
||||
{
|
||||
til::rle<UINT> actual(10, 10);
|
||||
til::rle<int> actual(10, 10);
|
||||
actual.insert(3, 0, 4);
|
||||
actual.insert(7, 4, 2);
|
||||
actual.insert(11, 6, 3);
|
||||
actual.insert(4, 9, 1);
|
||||
actual.fill(20, 2);
|
||||
|
||||
til::rle<UINT> expected(10, 20);
|
||||
til::rle<int> expected(10, 20);
|
||||
actual.insert(3, 0, 2);
|
||||
|
||||
VERIFY_ARE_EQUAL(expected, actual);
|
||||
|
|
Loading…
Reference in a new issue