feat(rtl): add _Utf8DecodeAt helper for UTF-8 codepoint decoding

Decodes one UTF-8 codepoint at a given byte index in a string. Returns
both the codepoint value and byte count packed into a single Int64:
(ByteCount shl 32) or CodePoint. This will be used by the for-in
codepoint iteration codegen and the StrUtils codepoint functions.
This commit is contained in:
Graeme Geldenhuys 2026-06-07 23:31:01 +01:00
parent dd2e5ddb47
commit d06cd40a0c

View file

@ -70,6 +70,16 @@ function _StringCompare(S1, S2: Pointer): Integer;
function _StringCompareText(S1, S2: Pointer): Integer;
function _StringFromPChar(P: PChar): Pointer;
{ ------------------------------------------------------------------ }
{ UTF-8 codepoint decoding }
{ ------------------------------------------------------------------ }
{ Decode one UTF-8 codepoint at byte position Idx in string S.
Returns a packed Int64: low 21 bits = codepoint value (0..U+10FFFF),
bits 32..33 = byte count consumed (1..4).
Caller extracts: CodePoint = Result and $1FFFFF; Advance = Result shr 32. }
function _Utf8DecodeAt(S: Pointer; Idx: Integer): Int64;
{ ------------------------------------------------------------------ }
{ Dynamic array RTL }
{ ------------------------------------------------------------------ }
@ -855,6 +865,43 @@ begin
MemCopy(StrData(Result), P, Len);
end;
{ ------------------------------------------------------------------ }
{ _Utf8DecodeAt }
{ ------------------------------------------------------------------ }
function _Utf8DecodeAt(S: Pointer; Idx: Integer): Int64;
var
P: PChar;
B0, B1, B2, B3: Integer;
CP: Integer;
begin
P := StrData(S);
B0 := P[Idx];
if B0 < 128 then
Result := (Int64(1) shl 32) or Int64(B0)
else if (B0 and $E0) = $C0 then
begin
B1 := P[Idx + 1] and $3F;
CP := ((B0 and $1F) shl 6) or B1;
Result := (Int64(2) shl 32) or Int64(CP);
end
else if (B0 and $F0) = $E0 then
begin
B1 := P[Idx + 1] and $3F;
B2 := P[Idx + 2] and $3F;
CP := ((B0 and $0F) shl 12) or (B1 shl 6) or B2;
Result := (Int64(3) shl 32) or Int64(CP);
end
else
begin
B1 := P[Idx + 1] and $3F;
B2 := P[Idx + 2] and $3F;
B3 := P[Idx + 3] and $3F;
CP := ((B0 and $07) shl 18) or (B1 shl 12) or (B2 shl 6) or B3;
Result := (Int64(4) shl 32) or Int64(CP);
end;
end;
{ ------------------------------------------------------------------ }
{ _StringFormat }
{ ------------------------------------------------------------------ }