AuroraRuntime/Source/Locale/Encoding/UTFn/AuUTF32.hpp

188 lines
5.0 KiB
C++
Raw Normal View History

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuUTF32.hpp
Date: 2021-10-31
Author: Reece
***/
#pragma once
namespace Aurora::Locale::Encoding::UTF32
{
static void SwapU32(void *base, AuUInt32 count)
{
count *= 4;
for (int i = 0; i < count; i += 4)
{
AuWriteU32BE(base, i, AuReadU32LE(base, i));
}
}
static AuUInt32 Count32(const void *base, AuUInt32 length, bool bytes = false)
{
return bytes ? length & ~3 : (length & ~3) / 4;
}
static bool WriteCp(AuUInt32 cp, char *& result, AuUInt32 &counter, AuUInt32 max)
{
if (cp < 0x80)
{
if (counter + 1 > max)
{
return false;
}
counter += 1;
*(result++) = static_cast<AuUInt8>(cp);
}
else if (cp < 0x800)
{
if (counter + 2 > max)
{
return false;
}
counter += 2;
*(result++) = static_cast<AuUInt8>((cp >> 6) | 0xc0);
*(result++) = static_cast<AuUInt8>((cp & 0x3f) | 0x80);
}
else if (cp < 0x10000)
{
if (counter + 3 > max)
{
return false;
}
counter += 3;
*(result++) = static_cast<AuUInt8>((cp >> 12) | 0xe0);
*(result++) = static_cast<AuUInt8>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>((cp & 0x3f) | 0x80);
}
else if (cp < 200000)
{
if (counter + 4 > max)
{
return false;
}
counter += 4;
*(result++) = static_cast<AuUInt8>((cp >> 18) | 0xf0);
*(result++) = static_cast<AuUInt8>(((cp >> 12) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>((cp & 0x3f) | 0x80);
}
else if (cp < 400000)
{
if (counter + 5 > max)
{
return false;
}
counter += 5;
*(result++) = static_cast<AuUInt8>((cp >> 24) | 0xf8);
*(result++) = static_cast<AuUInt8>(((cp >> 18) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>(((cp >> 12) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>((cp & 0x3f) | 0x80);
}
else if (cp < 80000000)
{
if (counter + 6 > max)
{
return false;
}
counter += 6;
*(result++) = static_cast<AuUInt8>((cp >> 30) | 0xfc);
*(result++) = static_cast<AuUInt8>(((cp >> 24) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>(((cp >> 18) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>(((cp >> 12) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<AuUInt8>((cp & 0x3f) | 0x80);
}
else
{
return false;
}
return true;
}
static bool ReadUtf8ByteString(AuUInt32 *cp, AuUInt32 *&cpEnd, const char *&s, const char *end)
{
if (!s)
{
return false;
}
if (!cp)
{
cpEnd = cp;
}
auto &it = s;
while ((it < end) && // can coomsome
(cp && cp < cpEnd))
{
AuUInt32 c = 0;
if (*it <= 0x7FU)
{
c = *it;
++it;
}
else
{
if ((*it & 0xC0U) != 0xC0U)
{
return false;
}
AuUInt32 nby = 0;
for (AuUInt8 b = *it; (b & 0x80U) != 0; b <<= 1, ++nby)
{}
if (nby > 6)
{
return false;
}
if ((end - it) < nby)
{
return false;
}
c = *it & (AuUInt8(0xFFU) >> (nby + 1));
for (AuUInt32 i = 1; i < nby; ++i)
{
if ((it[i] & 0xC0U) != 0x80U)
{
return false;
}
c = (c << 6) | (it[i] & 0x3FU);
}
it += nby;
}
if (cp)
{
*cp = c;
cp++;
}
cpEnd++;
}
}
static AuUInt32 CountU8Overhead(AuUInt32 cp)
{
if (cp < 0x80)
return 1;
else if (cp < 0x800)
return 2;
else if (cp < 0x10000)
return 3;
else if (cp < 200000)
return 4;
else if (cp < 400000)
return 5;
else if (cp < 80000000)
return 6;
}
}