static class · System

Unicode

public static class Unicode

Code points to and from UTF-8, UTF-16 and UTF-32 units (the unit type says which).

Kind
static class
Namespace
System
Assembly
System.Core
Access
public, static, abstract
Source file
String.ant

Inheritance

Base classes
Any Unicode

Methods

Decode<T : [u8, u16, u32]>(T[] units) : u32[]
#

static

The code points of units (UTF-8 for u8, UTF-16 for u16, UTF-32 for u32); malformed ones become U+FFFD.

EncodedLength<T : [u8, u16, u32]>(u32[] points) : i32
#

static

How many units of T points take.

Encode<T : [u8, u16, u32]>(u32[] points) : T[]
#

static

points as units of T (UTF-8, UTF-16 or UTF-32).

FromUtf16(u16[] units) : str
#

static

Text from UTF-16 units (what the runtime's services give): in UTF-8.

ToUtf16(str text) : u16[]
#

static

A str's text as UTF-16 units (what the runtime's services take).

ToString(u32 point) : str
#

static

One code point as a str.

Inherited members (5)

Source

Unicode as Antril, decompiled from its Larva HIR.

System.Unicode.ant
// System.Unicode — System.Core (decompiled from Larva HIR)

into namespace System
{
	/// Code points to and from UTF-8, UTF-16 and UTF-32 units (the unit type says which).
	public static class Unicode
	{
		public:
			/// The code points of `units` (UTF-8 for u8, UTF-16 for u16, UTF-32 for u32); malformed ones become U+FFFD.
			Decode<T : [u8, u16, u32]>(T[] units) : u32[]
			{
				u32[] points = new u32[units.Length];
				i32 count = 0;
				i32 i = 0;
				loop (i < units.Length)
				{
					u32 c = (u32)units[i];
					if (sizeof(T) == 4 || c < 128)
					{
						points[count] = sizeof(T) == 4 && (c > 1114111 || c >= 55296 && c <= 57343) ? 65533 : c;
						count++;
						i++;
						continue;
					}
					if (sizeof(T) == 2)
					{
						if (c >= 55296 && c <= 56319 && i + 1 < units.Length && (u32)units[i + 1] >= 56320 && (u32)units[i + 1] <= 57343)
						{
							points[count] = 65536 + (c - 55296 << 10) + ((u32)units[i + 1] - 56320);
							i += 2;
						}
						else
						{
							points[count] = c >= 55296 && c <= 57343 ? 65533 : c;
							i++;
						}
						count++;
						continue;
					}
					i32 extra = c >= 248 ? 0 : c >= 240 ? 3 : c >= 224 ? 2 : c >= 194 ? 1 : 0;
					if (extra == 0 || i + extra >= units.Length)
					{
						points[count] = 65533;
						count++;
						i++;
						continue;
					}
					u32 point = c & (extra == 1 ? 31 : extra == 2 ? 15 : 7);
					bool valid = true;
					loop (i32 k = 1..=extra)
					{
						u32 next = (u32)units[i + k];
						if ((next & 192) != 128)
							valid = false;
						point = point << 6 | next & 63;
					}
					if (!valid || extra == 2 && (point < 2048 || point >= 55296 && point <= 57343) || extra == 3 && (point < 65536 || point > 1114111))
					{
						points[count] = 65533;
						count++;
						i++;
						continue;
					}
					points[count] = point;
					count++;
					i += extra + 1;
				}
				return count == points.Length ? points : Array.Resize(points, count);
			}

			/// How many units of T `points` take.
			EncodedLength<T : [u8, u16, u32]>(u32[] points) : i32
			{
				i32 length = 0;
				loop (i32 i = 0..points.Length)
				{
					u32 c = points[i];
					if (sizeof(T) == 4)
						length += 1;
					else if (sizeof(T) == 2)
						length += c >= 65536 ? 2 : 1;
					else
						length += c < 128 ? 1 : c < 2048 ? 2 : c < 65536 ? 3 : 4;
				}
				return length;
			}

			/// `points` as units of T (UTF-8, UTF-16 or UTF-32).
			Encode<T : [u8, u16, u32]>(u32[] points) : T[]
			{
				T[] units = new T[EncodedLength<T>(points)];
				i32 at = 0;
				loop (i32 i = 0..points.Length)
				{
					u32 c = points[i];
					if (sizeof(T) == 4)
					{
						units[at] = (T)c;
						at++;
					}
					else if (sizeof(T) == 2)
					{
						if (c >= 65536)
						{
							u32 rest = c - 65536;
							units[at] = (T)(55296 + (rest >> 10));
							units[at + 1] = (T)(56320 + (rest & 1023));
							at += 2;
						}
						else
						{
							units[at] = (T)c;
							at++;
						}
					}
					else if (c < 128)
					{
						units[at] = (T)c;
						at++;
					}
					else if (c < 2048)
					{
						units[at] = (T)((u32)(T)192 | c >> 6);
						units[at + 1] = (T)((u32)(T)128 | c & (u32)(T)63);
						at += 2;
					}
					else if (c < 65536)
					{
						units[at] = (T)((u32)(T)224 | c >> 12);
						units[at + 1] = (T)((u32)(T)128 | c >> 6 & (u32)(T)63);
						units[at + 2] = (T)((u32)(T)128 | c & (u32)(T)63);
						at += 3;
					}
					else
					{
						units[at] = (T)((u32)(T)240 | c >> 18);
						units[at + 1] = (T)((u32)(T)128 | c >> 12 & (u32)(T)63);
						units[at + 2] = (T)((u32)(T)128 | c >> 6 & (u32)(T)63);
						units[at + 3] = (T)((u32)(T)128 | c & (u32)(T)63);
						at += 4;
					}
				}
				return units;
			}

			/// Text from UTF-16 units (what the runtime's services give): in UTF-8.
			FromUtf16(u16[] units) : str => new str(Encode<u8>(Decode(units)));

			/// A str's text as UTF-16 units (what the runtime's services take).
			ToUtf16(str text) : u16[] => Encode<u16>(Decode(text.Units()));

			/// One code point as a str.
			ToString(u32 point) : str
			{
				u32[] one = new u32[1];
				one[0] = point;
				return new str(Encode<u8>(one));
			}
	}
}
Esc