AuROXTL/Include/auROXTL/Iterators/auUTF8Iterator.ipp
2024-09-01 22:19:18 +01:00

283 lines
6.0 KiB
C++

/***
Copyright (C) 2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auUTF8Iterator.ipp
Date: 2024-08-31
Author: Reece
Notes: UTF8 iterator
***/
#pragma once
inline constexpr AuUTF8Iterator::AuUTF8Iterator()
{
}
inline constexpr AuUTF8Iterator::AuUTF8Iterator(const AuUTF8Iterator &copy) :
baseView(copy.baseView),
pCurrent(copy.pCurrent)
{
}
inline constexpr AuUTF8Iterator::AuUTF8Iterator(AuUTF8Iterator &&copy) :
baseView(copy.baseView),
pCurrent(copy.pCurrent)
{
}
inline constexpr AuUTF8Iterator &AuUTF8Iterator::operator =(const AuUTF8Iterator &copy)
{
this->baseView = copy.baseView;
this->baseView = copy.pCurrent;
return *this;
}
inline constexpr AuUTF8Iterator &AuUTF8Iterator::operator =(AuUTF8Iterator &&move)
{
this->baseView = move.baseView;
this->pCurrent = move.pCurrent;
return *this;
}
inline AuUTF8Iterator::AuUTF8Iterator(const char *pStart)
{
this->baseView = pStart;
this->pCurrent = pStart;
}
inline AuUTF8Iterator::AuUTF8Iterator(const AuROString &in, AuUInt uOffset)
{
this->baseView = in;
this->pCurrent = in.Begin();
if (uOffset != AuROString::npos)
{
auto out = AuCodepointsGetByteOffset(in, uOffset);
if (out != AuROString::npos)
{
this->pCurrent += out;
}
else
{
this->pCurrent = in.End();
}
}
}
AuUTF8Iterator AuUTF8Iterator::FromStringView(AuROString in, AuUInt uOffset)
{
return AuUTF8Iterator(in, uOffset);
}
inline constexpr const char *AuUTF8Iterator::base() const
{
return this->pCurrent;
}
inline constexpr const char *AuUTF8Iterator::Base() const
{
return this->pCurrent;
}
inline constexpr AuUTF8Iterator AuUTF8Iterator::end() const
{
AuUTF8Iterator ret;
ret.baseView = this->baseView;
ret.pCurrent = this->baseView.End();
return ret;
}
inline constexpr AuUTF8Iterator AuUTF8Iterator::End() const
{
AuUTF8Iterator ret;
ret.baseView = this->baseView;
ret.pCurrent = this->baseView.End();
return ret;
}
inline constexpr AuOptional<AuUInt32> AuUTF8Iterator::operator*() const
{
auto pBegin = this->baseView.Begin();
auto uDiff = this->pCurrent - pBegin;
auto uLength = this->baseView.Length();
if (uLength == uDiff)
{
return {};
}
auto pNext = pBegin + uDiff;
auto uNext = uLength - uDiff;
return AuCodepointsDecodeOne(AuROString(pNext, uNext));
}
inline constexpr AuUTF8Iterator::pointer AuUTF8Iterator::operator->() const
{
return this->base();
}
inline constexpr AuUTF8Iterator &AuUTF8Iterator::operator++()
{
auto pBegin = this->baseView.Begin();
auto uDiff = this->pCurrent - pBegin;
auto uLength = this->baseView.Length();
if (uLength == uDiff)
{
return *this;
}
auto pNext = pBegin + uDiff;
auto uNext = uLength - uDiff;
if (auto uCount = AuCodepointsNextLength(AuROString(pNext, uNext)))
{
this->pCurrent += uCount;
}
else
{
*this = this->End();
}
return *this;
}
inline constexpr AuUTF8Iterator AuUTF8Iterator::operator++(int)
{
AuUTF8Iterator ret = *this;
++ret;
return ret;
}
inline constexpr AuUTF8Iterator &AuUTF8Iterator::operator--()
{
auto pBegin = this->baseView.Begin();
auto uDiff = this->pCurrent - pBegin;
auto uLength = this->baseView.Length();
if (uLength == uDiff)
{
return *this;
}
{
auto uOffset = AuCodepointsFindPreviousValidByteOffsetFromByteOffset(this->baseView, uDiff);
if (uOffset != AuString::npos)
{
this->pCurrent = pBegin + uOffset;
}
else
{
this->pCurrent = pBegin;
return *this;
}
}
return *this;
}
inline constexpr AuUTF8Iterator AuUTF8Iterator::operator--(int)
{
AuUTF8Iterator ret = *this;
--ret;
return ret;
}
inline constexpr AuUTF8Iterator AuUTF8Iterator::operator+(const difference_type offset) const
{
AuUTF8Iterator copy = *this;
copy += offset;
return copy;
}
inline constexpr AuUTF8Iterator &AuUTF8Iterator::operator+=(const difference_type offset)
{
auto pBegin = this->baseView.Begin();
auto uDiff = this->pCurrent - pBegin;
auto uLength = this->baseView.Length();
if (uLength == uDiff ||
offset == 0)
{
return *this;
}
if (offset < 0)
{
(*this)-= 0 - offset;
return *this;
}
auto pNext = pBegin + uDiff;
auto uNext = uLength - uDiff;
for (AU_ITERATE_N(i, AuUInt(offset)))
{
if (auto uCount = AuCodepointsNextLength(AuROString(pNext, uNext)))
{
pNext += uCount;
uNext -= uCount;
this->pCurrent += uCount;
}
else
{
*this = this->End();
return *this;
}
}
return *this;
}
inline constexpr AuUTF8Iterator AuUTF8Iterator::operator-(const difference_type offset) const
{
AuUTF8Iterator copy = *this;
copy -= offset;
return copy;
}
inline constexpr AuUTF8Iterator &AuUTF8Iterator::operator-=(const difference_type offset)
{
auto pBegin = this->baseView.Begin();
auto uDiff = this->pCurrent - pBegin;
auto uLength = this->baseView.Length();
if (uLength == uDiff ||
offset == 0)
{
return *this;
}
if (offset < 0)
{
(*this)+= 0 - offset;
return *this;
}
for (AU_ITERATE_N(i, AuUInt(offset)))
{
auto uOffset = AuCodepointsFindPreviousValidByteOffsetFromByteOffset(this->baseView, uDiff);
if (uOffset != AuString::npos)
{
this->pCurrent = pBegin + uOffset;
uDiff = uOffset;
}
else
{
this->pCurrent = pBegin;
return *this;
}
}
return *this;
}
inline constexpr AuOptional<AuUInt32> AuUTF8Iterator::operator[](const difference_type offset) const
{
auto ret = *this;
ret += offset;
return *ret;
}