283 lines
6.0 KiB
C++
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 ©) :
|
|
baseView(copy.baseView),
|
|
pCurrent(copy.pCurrent)
|
|
{
|
|
|
|
}
|
|
|
|
inline constexpr AuUTF8Iterator::AuUTF8Iterator(AuUTF8Iterator &©) :
|
|
baseView(copy.baseView),
|
|
pCurrent(copy.pCurrent)
|
|
{
|
|
|
|
}
|
|
|
|
inline constexpr AuUTF8Iterator &AuUTF8Iterator::operator =(const AuUTF8Iterator ©)
|
|
{
|
|
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;
|
|
} |