/*** 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 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 AuUTF8Iterator::operator[](const difference_type offset) const { auto ret = *this; ret += offset; return *ret; }