Remove the OCI sources

This commit is contained in:
Dustin Howett 2021-07-29 16:44:47 -05:00
parent 7c5b39a041
commit 271132edb4
3 changed files with 0 additions and 1189 deletions

View file

@ -1,542 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "OutputCellIterator.hpp"
#include "TextBufferCellIterator.hpp"
#include "../../types/inc/convert.hpp"
#include "../../types/inc/Utf16Parser.hpp"
#include "../../types/inc/GlyphWidth.hpp"
#include "../../inc/conattrs.hpp"
static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLOR };
// Routine Description:
// - This is a fill-mode iterator for one particular wchar. It will repeat forever if fillLimit is 0.
// Arguments:
// - wch - The character to use for filling
// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
OutputCellIterator::OutputCellIterator(const wchar_t& wch, const size_t fillLimit) noexcept :
_mode(Mode::Fill),
_currentView(s_GenerateView(wch)),
_run(),
_attr(InvalidTextAttribute),
_pos(0),
_distance(0),
_fillLimit(fillLimit)
{
}
// Routine Description:
// - This is a fill-mode iterator for one particular character and color. It will repeat forever if fillLimit is 0.
// Arguments:
// - wch - The character to use for filling
// - attr - The color attribute to use for filling
// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
OutputCellIterator::OutputCellIterator(const wchar_t& wch, const TextAttribute& attr, const size_t fillLimit) noexcept :
_mode(Mode::Fill),
_currentView(s_GenerateView(wch, attr)),
_run(),
_attr(InvalidTextAttribute),
_pos(0),
_distance(0),
_fillLimit(fillLimit)
{
}
// Routine Description:
// - This is a fill-mode iterator for one particular CHAR_INFO. It will repeat forever if fillLimit is 0.
// Arguments:
// - charInfo - The legacy character and color data to use for filling (uses Unicode portion of text data)
// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
OutputCellIterator::OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit) noexcept :
_mode(Mode::Fill),
_currentView(s_GenerateView(charInfo)),
_run(),
_attr(InvalidTextAttribute),
_pos(0),
_distance(0),
_fillLimit(fillLimit)
{
}
// Routine Description:
// - This is an iterator over a range text that will apply the same color to every position.
// Arguments:
// - utf16Text - UTF-16 text range
// - attribute - Color to apply over the entire range
OutputCellIterator::OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute attribute) :
_mode(Mode::Loose),
_currentView(s_GenerateView(utf16Text, attribute)),
_run(utf16Text),
_attr(attribute),
_distance(0),
_pos(0),
_fillLimit(0)
{
}
// Routine Description:
// - This is an iterator over legacy colors only. The text is not modified.
// Arguments:
// - legacyAttrs - One legacy color item per cell
OutputCellIterator::OutputCellIterator(const gsl::span<const WORD> legacyAttrs) noexcept :
_mode(Mode::LegacyAttr),
_currentView(s_GenerateViewLegacyAttr(til::at(legacyAttrs, 0))),
_run(legacyAttrs),
_attr(InvalidTextAttribute),
_distance(0),
_pos(0),
_fillLimit(0)
{
}
// Routine Description:
// - This is an iterator over legacy cell data. We will use the unicode text and the legacy color attribute.
// Arguments:
// - charInfos - Multiple cell with unicode text and legacy color data.
OutputCellIterator::OutputCellIterator(const gsl::span<const CHAR_INFO> charInfos) noexcept :
_mode(Mode::CharInfo),
_currentView(s_GenerateView(til::at(charInfos, 0))),
_run(charInfos),
_attr(InvalidTextAttribute),
_distance(0),
_pos(0),
_fillLimit(0)
{
}
// Routine Description:
// - This is an iterator over existing OutputCells with full text and color data.
// Arguments:
// - cells - Multiple cells in a run
OutputCellIterator::OutputCellIterator(const gsl::span<const OutputCell> cells) :
_mode(Mode::Cell),
_currentView(s_GenerateView(til::at(cells, 0))),
_run(cells),
_attr(InvalidTextAttribute),
_distance(0),
_pos(0),
_fillLimit(0)
{
}
OutputCellIterator::OutputCellIterator(TextBufferCellIterator start) :
_mode(Mode::BufferCopy),
_run(start),
_currentView(*start),
_attr(InvalidTextAttribute),
_distance(0),
_pos(0),
_fillLimit(0)
{
}
// Routine Description:
// - Specifies whether this iterator is valid for dereferencing (still valid underlying data)
// Return Value:
// - True if the views on dereference are valid. False if it shouldn't be dereferenced.
OutputCellIterator::operator bool() const noexcept
{
try
{
switch (_mode)
{
case Mode::Loose:
case Mode::LooseTextOnly:
{
// In lieu of using start and end, this custom iterator type simply becomes bool false
// when we run out of items to iterate over.
return _pos < std::get<std::wstring_view>(_run).length();
}
case Mode::Fill:
{
if (_fillLimit > 0)
{
return _pos < _fillLimit;
}
return true;
}
case Mode::Cell:
{
return _pos < std::get<gsl::span<const OutputCell>>(_run).size();
}
case Mode::CharInfo:
{
return _pos < std::get<gsl::span<const CHAR_INFO>>(_run).size();
}
case Mode::LegacyAttr:
{
return _pos < std::get<gsl::span<const WORD>>(_run).size();
}
case Mode::BufferCopy:
{
auto& it = std::get<TextBufferCellIterator>(_run);
return (bool)it;
}
default:
FAIL_FAST_HR(E_NOTIMPL);
}
}
CATCH_FAIL_FAST();
}
// Routine Description:
// - Advances the iterator one position over the underlying data source.
// Return Value:
// - Reference to self after advancement.
OutputCellIterator& OutputCellIterator::operator++()
{
// Keep track of total distance moved (cells filled)
_distance++;
switch (_mode)
{
case Mode::Loose:
{
if (!_TryMoveTrailing())
{
// When walking through a text sequence, we need to move forward by the number of wchar_ts consumed in the previous view
// in case we had a surrogate pair (or wider complex sequence) in the previous view.
_pos += _currentView.Chars().size();
if (operator bool())
{
_currentView = s_GenerateView(std::get<std::wstring_view>(_run).substr(_pos), _attr);
}
}
break;
}
case Mode::LooseTextOnly:
{
if (!_TryMoveTrailing())
{
// When walking through a text sequence, we need to move forward by the number of wchar_ts consumed in the previous view
// in case we had a surrogate pair (or wider complex sequence) in the previous view.
_pos += _currentView.Chars().size();
if (operator bool())
{
_currentView = s_GenerateView(std::get<std::wstring_view>(_run).substr(_pos));
}
}
break;
}
case Mode::Fill:
{
if (!_TryMoveTrailing())
{
if (_currentView.DbcsAttr().IsTrailing())
{
auto dbcsAttr = _currentView.DbcsAttr();
dbcsAttr.SetLeading();
_currentView = OutputCellView(_currentView.Chars(),
dbcsAttr,
_currentView.TextAttr(),
_currentView.TextAttrBehavior());
}
if (_fillLimit > 0)
{
// We walk forward by one because we fill with the same cell over and over no matter what
_pos++;
}
}
break;
}
case Mode::Cell:
{
// Walk forward by one because cells are assumed to be in the form they needed to be
_pos++;
if (operator bool())
{
_currentView = s_GenerateView(til::at(std::get<gsl::span<const OutputCell>>(_run), _pos));
}
break;
}
case Mode::CharInfo:
{
// Walk forward by one because charinfos are just the legacy version of cells and prealigned to columns
_pos++;
if (operator bool())
{
_currentView = s_GenerateView(til::at(std::get<gsl::span<const CHAR_INFO>>(_run), _pos));
}
break;
}
case Mode::LegacyAttr:
{
// Walk forward by one because color attributes apply cell by cell (no complex text information)
_pos++;
if (operator bool())
{
_currentView = s_GenerateViewLegacyAttr(til::at(std::get<gsl::span<const WORD>>(_run), _pos));
}
break;
}
case Mode::BufferCopy:
{
auto& it = std::get<TextBufferCellIterator>(_run);
if (++it)
{
_pos++;
_currentView = *it;
}
break;
}
default:
FAIL_FAST_HR(E_NOTIMPL);
}
return (*this);
}
// Routine Description:
// - Advances the iterator one position over the underlying data source.
// Return Value:
// - Reference to self after advancement.
OutputCellIterator OutputCellIterator::operator++(int)
{
auto temp(*this);
operator++();
return temp;
}
// Routine Description:
// - Reference the view to fully-formed output cell data representing the underlying data source.
// Return Value:
// - Reference to the view
const OutputCellView& OutputCellIterator::operator*() const noexcept
{
return _currentView;
}
// Routine Description:
// - Get pointer to the view to fully-formed output cell data representing the underlying data source.
// Return Value:
// - Pointer to the view
const OutputCellView* OutputCellIterator::operator->() const noexcept
{
return &_currentView;
}
// Routine Description:
// - Checks the current view. If it is a leading half, it updates the current
// view to the trailing half of the same glyph.
// - This helps us to draw glyphs that are two columns wide by "doubling"
// the view that is returned so it will consume two cells.
// Return Value:
// - True if we just turned a lead half into a trailing half (and caller doesn't
// need to further update the view).
// - False if this wasn't applicable and the caller should update the view.
bool OutputCellIterator::_TryMoveTrailing() noexcept
{
if (_currentView.DbcsAttr().IsLeading())
{
auto dbcsAttr = _currentView.DbcsAttr();
dbcsAttr.SetTrailing();
_currentView = OutputCellView(_currentView.Chars(),
dbcsAttr,
_currentView.TextAttr(),
_currentView.TextAttrBehavior());
return true;
}
else
{
return false;
}
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// - This will infer the width of the glyph and specify that the attributes shouldn't be changed.
// Arguments:
// - view - View representing characters corresponding to a single glyph
// Return Value:
// - Object representing the view into this cell
OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view)
{
return s_GenerateView(view, InvalidTextAttribute, TextAttributeBehavior::Current);
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// - This will infer the width of the glyph and apply the appropriate attributes to the view.
// Arguments:
// - view - View representing characters corresponding to a single glyph
// - attr - Color attributes to apply to the text
// Return Value:
// - Object representing the view into this cell
OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view,
const TextAttribute attr)
{
return s_GenerateView(view, attr, TextAttributeBehavior::Stored);
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// - This will infer the width of the glyph and apply the appropriate attributes to the view.
// Arguments:
// - view - View representing characters corresponding to a single glyph
// - attr - Color attributes to apply to the text
// - behavior - Behavior of the given text attribute (used when writing)
// Return Value:
// - Object representing the view into this cell
OutputCellView OutputCellIterator::s_GenerateView(const std::wstring_view view,
const TextAttribute attr,
const TextAttributeBehavior behavior)
{
const auto glyph = Utf16Parser::ParseNext(view);
DbcsAttribute dbcsAttr;
if (IsGlyphFullWidth(glyph))
{
dbcsAttr.SetLeading();
}
return OutputCellView(glyph, dbcsAttr, attr, behavior);
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// - This will infer the width of the glyph and apply the appropriate attributes to the view.
// Arguments:
// - wch - View representing a single UTF-16 character (that can be represented without surrogates)
// Return Value:
// - Object representing the view into this cell
OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch) noexcept
{
const auto glyph = std::wstring_view(&wch, 1);
DbcsAttribute dbcsAttr;
if (IsGlyphFullWidth(wch))
{
dbcsAttr.SetLeading();
}
return OutputCellView(glyph, dbcsAttr, InvalidTextAttribute, TextAttributeBehavior::Current);
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// - This will infer the width of the glyph and apply the appropriate attributes to the view.
// Arguments:
// - attr - View representing a single color
// Return Value:
// - Object representing the view into this cell
OutputCellView OutputCellIterator::s_GenerateView(const TextAttribute& attr) noexcept
{
return OutputCellView({}, {}, attr, TextAttributeBehavior::StoredOnly);
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// - This will infer the width of the glyph and apply the appropriate attributes to the view.
// Arguments:
// - wch - View representing a single UTF-16 character (that can be represented without surrogates)
// - attr - View representing a single color
// Return Value:
// - Object representing the view into this cell
OutputCellView OutputCellIterator::s_GenerateView(const wchar_t& wch, const TextAttribute& attr) noexcept
{
const auto glyph = std::wstring_view(&wch, 1);
DbcsAttribute dbcsAttr;
if (IsGlyphFullWidth(wch))
{
dbcsAttr.SetLeading();
}
return OutputCellView(glyph, dbcsAttr, attr, TextAttributeBehavior::Stored);
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// - This will infer the width of the glyph and apply the appropriate attributes to the view.
// Arguments:
// - legacyAttr - View representing a single legacy color
// Return Value:
// - Object representing the view into this cell
OutputCellView OutputCellIterator::s_GenerateViewLegacyAttr(const WORD& legacyAttr) noexcept
{
WORD cleanAttr = legacyAttr;
WI_ClearAllFlags(cleanAttr, COMMON_LVB_SBCSDBCS); // don't use legacy lead/trailing byte flags for colors
const TextAttribute attr(cleanAttr);
return s_GenerateView(attr);
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// - This will infer the width of the glyph and apply the appropriate attributes to the view.
// Arguments:
// - charInfo - character and attribute pair representing a single cell
// Return Value:
// - Object representing the view into this cell
OutputCellView OutputCellIterator::s_GenerateView(const CHAR_INFO& charInfo) noexcept
{
const auto glyph = std::wstring_view(&charInfo.Char.UnicodeChar, 1);
DbcsAttribute dbcsAttr;
if (WI_IsFlagSet(charInfo.Attributes, COMMON_LVB_LEADING_BYTE))
{
dbcsAttr.SetLeading();
}
else if (WI_IsFlagSet(charInfo.Attributes, COMMON_LVB_TRAILING_BYTE))
{
dbcsAttr.SetTrailing();
}
const TextAttribute textAttr(charInfo.Attributes);
const auto behavior = TextAttributeBehavior::Stored;
return OutputCellView(glyph, dbcsAttr, textAttr, behavior);
}
// Routine Description:
// - Static function to create a view.
// - It's pulled out statically so it can be used during construction with just the given
// variables (so OutputCellView doesn't need an empty default constructor)
// Arguments:
// - cell - A reference to the cell for which we will make the read-only view
// Return Value:
// - Object representing the view into this cell
OutputCellView OutputCellIterator::s_GenerateView(const OutputCell& cell)
{
return OutputCellView(cell.Chars(), cell.DbcsAttr(), cell.TextAttr(), cell.TextAttrBehavior());
}
// Routine Description:
// - Gets the distance between two iterators relative to the input data given in.
// Return Value:
// - The number of items of the input run consumed between these two iterators.
ptrdiff_t OutputCellIterator::GetInputDistance(OutputCellIterator other) const noexcept
{
return _pos - other._pos;
}
// Routine Description:
// - Gets the distance between two iterators relative to the number of cells inserted.
// Return Value:
// - The number of cells in the backing buffer filled between these two iterators.
ptrdiff_t OutputCellIterator::GetCellDistance(OutputCellIterator other) const noexcept
{
return _distance - other._distance;
}

View file

@ -1,133 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- OutputCellIterator.hpp
Abstract:
- Read-only view into an entire batch of data to be written into the output buffer.
- This is done for performance reasons (avoid heap allocs and copies).
Author:
- Michael Niksa (MiNiksa) 06-Oct-2018
Revision History:
- Based on work from OutputCell.hpp/cpp by Austin Diviness (AustDi)
--*/
#pragma once
#include "TextAttribute.hpp"
#include "OutputCell.hpp"
#include "OutputCellView.hpp"
#include "TextBufferCellIterator.hpp"
class OutputCellIterator final
{
public:
using iterator_category = std::input_iterator_tag;
using value_type = OutputCellView;
using difference_type = ptrdiff_t;
using pointer = OutputCellView*;
using reference = OutputCellView&;
OutputCellIterator(const wchar_t& wch, const size_t fillLimit = 0) noexcept;
OutputCellIterator(const wchar_t& wch, const TextAttribute& attr, const size_t fillLimit = 0) noexcept;
OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit = 0) noexcept;
OutputCellIterator(const std::wstring_view utf16Text);
OutputCellIterator(const std::wstring_view utf16Text, const TextAttribute attribute);
OutputCellIterator(const gsl::span<const WORD> legacyAttributes) noexcept;
OutputCellIterator(const gsl::span<const CHAR_INFO> charInfos) noexcept;
OutputCellIterator(const gsl::span<const OutputCell> cells);
OutputCellIterator(TextBufferCellIterator start);
~OutputCellIterator() = default;
OutputCellIterator& operator=(const OutputCellIterator& it) = default;
operator bool() const noexcept;
ptrdiff_t GetCellDistance(OutputCellIterator other) const noexcept;
ptrdiff_t GetInputDistance(OutputCellIterator other) const noexcept;
friend ptrdiff_t operator-(OutputCellIterator one, OutputCellIterator two) = delete;
void AddCellDistanceFault(ptrdiff_t fault) { _distance += fault; };
OutputCellIterator& operator++();
OutputCellIterator operator++(int);
const OutputCellView& operator*() const noexcept;
const OutputCellView* operator->() const noexcept;
private:
enum class Mode
{
// Loose mode is where we're given text and attributes in a raw sort of form
// like while data is being inserted from an API call.
Loose,
// Loose mode with only text is where we're given just text and we want
// to use the attribute already in the buffer when writing
LooseTextOnly,
// Fill mode is where we were given one thing and we just need to keep giving
// that back over and over for eternity.
Fill,
// Given a run of legacy attributes, convert each of them and insert only attribute data.
LegacyAttr,
// CharInfo mode is where we've been given a pair of text and attribute for each
// cell in the legacy format from an API call.
CharInfo,
// Cell mode is where we have an already fully structured cell data usually
// from accessing/copying data already put into the OutputBuffer.
Cell,
// BufferCopy mode is where we're starting from a TextBufferCellIterator,
// which produces fully-formed cells out of another buffer.
BufferCopy,
};
Mode _mode;
gsl::span<const WORD> _legacyAttrs;
std::variant<
std::wstring_view,
gsl::span<const WORD>,
gsl::span<const CHAR_INFO>,
gsl::span<const OutputCell>,
TextBufferCellIterator,
std::monostate>
_run;
TextAttribute _attr;
bool _TryMoveTrailing() noexcept;
static OutputCellView s_GenerateView(const std::wstring_view view);
static OutputCellView s_GenerateView(const std::wstring_view view,
const TextAttribute attr);
static OutputCellView s_GenerateView(const std::wstring_view view,
const TextAttribute attr,
const TextAttributeBehavior behavior);
static OutputCellView s_GenerateView(const wchar_t& wch) noexcept;
static OutputCellView s_GenerateViewLegacyAttr(const WORD& legacyAttr) noexcept;
static OutputCellView s_GenerateView(const TextAttribute& attr) noexcept;
static OutputCellView s_GenerateView(const wchar_t& wch, const TextAttribute& attr) noexcept;
static OutputCellView s_GenerateView(const CHAR_INFO& charInfo) noexcept;
static OutputCellView s_GenerateView(const OutputCell& cell);
OutputCellView _currentView;
size_t _pos;
size_t _distance;
size_t _fillLimit;
};

View file

@ -1,514 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "WexTestClass.h"
#include "../../inc/consoletaeftemplates.hpp"
#include "../buffer/out/outputCellIterator.hpp"
using namespace WEX::Common;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
static constexpr TextAttribute InvalidTextAttribute{ INVALID_COLOR, INVALID_COLOR };
class OutputCellIteratorTests
{
CommonState* m_state;
TEST_CLASS(OutputCellIteratorTests);
TEST_METHOD(CharacterFillDoubleWidth)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const wchar_t wch = L'\x30a2'; // katakana A
const size_t limit = 5;
OutputCellIterator it(wch, limit);
OutputCellView expectedLead({ &wch, 1 },
DbcsAttribute(DbcsAttribute::Attribute::Leading),
InvalidTextAttribute,
TextAttributeBehavior::Current);
OutputCellView expectedTrail({ &wch, 1 },
DbcsAttribute(DbcsAttribute::Attribute::Trailing),
InvalidTextAttribute,
TextAttributeBehavior::Current);
for (size_t i = 0; i < limit; i++)
{
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expectedLead, *it);
it++;
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expectedTrail, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(CharacterFillLimited)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const wchar_t wch = L'Q';
const size_t limit = 5;
OutputCellIterator it(wch, limit);
OutputCellView expected({ &wch, 1 },
DbcsAttribute{},
InvalidTextAttribute,
TextAttributeBehavior::Current);
for (size_t i = 0; i < limit; i++)
{
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(CharacterFillUnlimited)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const wchar_t wch = L'Q';
OutputCellIterator it(wch);
OutputCellView expected({ &wch, 1 },
DbcsAttribute{},
InvalidTextAttribute,
TextAttributeBehavior::Current);
for (size_t i = 0; i < SHORT_MAX; i++)
{
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_TRUE(it);
}
TEST_METHOD(AttributeFillLimited)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const TextAttribute attr(FOREGROUND_RED | BACKGROUND_BLUE);
const size_t limit = 5;
OutputCellIterator it(attr, limit);
OutputCellView expected({},
{},
attr,
TextAttributeBehavior::StoredOnly);
for (size_t i = 0; i < limit; i++)
{
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(AttributeFillUnlimited)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const TextAttribute attr(FOREGROUND_RED | BACKGROUND_BLUE);
OutputCellIterator it(attr);
OutputCellView expected({},
{},
attr,
TextAttributeBehavior::StoredOnly);
for (size_t i = 0; i < SHORT_MAX; i++)
{
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_TRUE(it);
}
TEST_METHOD(TextAndAttributeFillLimited)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const wchar_t wch = L'Q';
const TextAttribute attr(FOREGROUND_RED | BACKGROUND_BLUE);
const size_t limit = 5;
OutputCellIterator it(wch, attr, limit);
OutputCellView expected({ &wch, 1 },
{},
attr,
TextAttributeBehavior::Stored);
for (size_t i = 0; i < limit; i++)
{
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(TextAndAttributeFillUnlimited)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const wchar_t wch = L'Q';
const TextAttribute attr(FOREGROUND_RED | BACKGROUND_BLUE);
OutputCellIterator it(wch, attr);
OutputCellView expected({ &wch, 1 },
{},
attr,
TextAttributeBehavior::Stored);
for (size_t i = 0; i < SHORT_MAX; i++)
{
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_TRUE(it);
}
TEST_METHOD(CharInfoFillLimited)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
CHAR_INFO ci;
ci.Char.UnicodeChar = L'Q';
ci.Attributes = FOREGROUND_RED | BACKGROUND_BLUE;
const size_t limit = 5;
OutputCellIterator it(ci, limit);
OutputCellView expected({ &ci.Char.UnicodeChar, 1 },
{},
TextAttribute(ci.Attributes),
TextAttributeBehavior::Stored);
for (size_t i = 0; i < limit; i++)
{
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(CharInfoFillUnlimited)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
CHAR_INFO ci;
ci.Char.UnicodeChar = L'Q';
ci.Attributes = FOREGROUND_RED | BACKGROUND_BLUE;
OutputCellIterator it(ci);
OutputCellView expected({ &ci.Char.UnicodeChar, 1 },
{},
TextAttribute(ci.Attributes),
TextAttributeBehavior::Stored);
for (size_t i = 0; i < SHORT_MAX; i++)
{
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_TRUE(it);
}
TEST_METHOD(StringData)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const std::wstring testText(L"The quick brown fox jumps over the lazy dog.");
OutputCellIterator it(testText);
for (const auto& wch : testText)
{
OutputCellView expected({ &wch, 1 },
{},
InvalidTextAttribute,
TextAttributeBehavior::Current);
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(FullWidthStringData)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const std::wstring testText(L"\x30a2\x30a3\x30a4\x30a5\x30a6");
OutputCellIterator it(testText);
for (const auto& wch : testText)
{
auto expected = OutputCellView({ &wch, 1 },
DbcsAttribute(DbcsAttribute::Attribute::Leading),
InvalidTextAttribute,
TextAttributeBehavior::Current);
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
expected = OutputCellView({ &wch, 1 },
DbcsAttribute(DbcsAttribute::Attribute::Trailing),
InvalidTextAttribute,
TextAttributeBehavior::Current);
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(StringDataWithColor)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const std::wstring testText(L"The quick brown fox jumps over the lazy dog.");
const TextAttribute color(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
OutputCellIterator it(testText, color);
for (const auto& wch : testText)
{
OutputCellView expected({ &wch, 1 },
{},
color,
TextAttributeBehavior::Stored);
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(FullWidthStringDataWithColor)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const std::wstring testText(L"\x30a2\x30a3\x30a4\x30a5\x30a6");
const TextAttribute color(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
OutputCellIterator it(testText, color);
for (const auto& wch : testText)
{
auto expected = OutputCellView({ &wch, 1 },
DbcsAttribute(DbcsAttribute::Attribute::Leading),
color,
TextAttributeBehavior::Stored);
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
expected = OutputCellView({ &wch, 1 },
DbcsAttribute(DbcsAttribute::Attribute::Trailing),
color,
TextAttributeBehavior::Stored);
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(LegacyColorDataRun)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const std::vector<WORD> colors{ FOREGROUND_GREEN, FOREGROUND_RED | BACKGROUND_BLUE, FOREGROUND_BLUE | FOREGROUND_INTENSITY, BACKGROUND_GREEN };
const gsl::span<const WORD> view{ colors.data(), colors.size() };
OutputCellIterator it(view);
for (const auto& color : colors)
{
auto expected = OutputCellView({},
{},
TextAttribute{ color },
TextAttributeBehavior::StoredOnly);
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(LegacyCharInfoRun)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
std::vector<CHAR_INFO> charInfos;
for (auto i = 0; i < 5; i++)
{
CHAR_INFO ci;
ci.Char.UnicodeChar = static_cast<wchar_t>(L'A' + i);
ci.Attributes = gsl::narrow<WORD>(i);
charInfos.push_back(ci);
}
const gsl::span<const CHAR_INFO> view{ charInfos.data(), charInfos.size() };
OutputCellIterator it(view);
for (const auto& ci : charInfos)
{
auto expected = OutputCellView({ &ci.Char.UnicodeChar, 1 },
{},
TextAttribute{ ci.Attributes },
TextAttributeBehavior::Stored);
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(OutputCellRun)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
std::vector<OutputCell> cells;
for (auto i = 0; i < 5; i++)
{
const std::wstring pair(L"\xd834\xdd1e");
OutputCell cell(pair, {}, TextAttribute{ gsl::narrow<WORD>(i) });
cells.push_back(cell);
}
const gsl::span<const OutputCell> view{ cells.data(), cells.size() };
OutputCellIterator it(view);
for (const auto& cell : cells)
{
auto expected = OutputCellView(cell.Chars(),
cell.DbcsAttr(),
cell.TextAttr(),
cell.TextAttrBehavior());
VERIFY_IS_TRUE(it);
VERIFY_ARE_EQUAL(expected, *it);
it++;
}
VERIFY_IS_FALSE(it);
}
TEST_METHOD(DistanceStandard)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const std::wstring testText(L"The quick brown fox jumps over the lazy dog.");
OutputCellIterator it(testText);
const auto original = it;
ptrdiff_t expected = 0;
for (const auto& wch : testText)
{
wch; // unused
VERIFY_IS_TRUE(it);
it++;
expected++;
}
VERIFY_IS_FALSE(it);
VERIFY_ARE_EQUAL(expected, it.GetCellDistance(original));
VERIFY_ARE_EQUAL(expected, it.GetInputDistance(original));
}
TEST_METHOD(DistanceFullWidth)
{
SetVerifyOutput settings(VerifyOutputSettings::LogOnlyFailures);
const std::wstring testText(L"QWER\x30a2\x30a3\x30a4\x30a5\x30a6TYUI");
OutputCellIterator it(testText);
const auto original = it;
ptrdiff_t cellsExpected = 0;
ptrdiff_t inputExpected = 0;
for (const auto& wch : testText)
{
wch; // unused
VERIFY_IS_TRUE(it);
const auto value = *it;
it++;
if (value.DbcsAttr().IsLeading() || value.DbcsAttr().IsTrailing())
{
VERIFY_IS_TRUE(it);
it++;
cellsExpected++;
}
cellsExpected++;
inputExpected++;
}
VERIFY_IS_FALSE(it);
VERIFY_ARE_EQUAL(cellsExpected, it.GetCellDistance(original));
VERIFY_ARE_EQUAL(inputExpected, it.GetInputDistance(original));
}
};